Skip to content

ChandraMohanBusam/mcp-notification-server

Repository files navigation

MCP Notification Server

A reusable MCP (Model Context Protocol) notification server designed to be the shared communication layer in a multi-agent architecture. Built as the natural evolution of the AI Deployment Agent (Approach B).

Any AI agent that needs to send notifications connects to this server as a dependency rather than implementing notification logic itself. One server, all channels, shared by all agents.


Why This Exists

In the AI Deployment Agent, email notification was implemented directly inside the deployment MCP server. This works well for a single agent. But as a system grows to multiple agents (deployment, incident response, monitoring, alerts), each agent duplicating notification logic is the wrong pattern.

The correct architecture is a dedicated notification server that all agents share:

Deployment Agent    ----+
Incident Agent      ----|----> MCP Notification Server
Monitoring Agent    ----+      (this repo)
Alert Agent         ----+

This is the MCP composition pattern: multiple single-responsibility servers, each doing one thing well, orchestrated by the agent layer.


Tools (8 Total)

Tool Purpose
send_email Send email via SMTP (plain text or HTML)
send_slack_message Post message to a Slack channel
send_teams_message Post a card to Microsoft Teams via webhook
schedule_reminder Schedule a notification to fire after N minutes
list_reminders List all scheduled and fired reminders
cancel_reminder Cancel a pending reminder by ID
get_notification_history Query audit log with optional filters

Tech Stack

Component Technology
MCP server FastMCP (mcp>=1.25)
Email Python smtplib + SMTP (Gmail, Outlook, or custom)
Slack Slack Web API (chat.postMessage)
Teams Incoming webhook (MessageCard)
Reminders Python threading + in-memory store
Agent consumption LangChain ReAct + LangGraph ReAct
LLM GPT-4o (temperature=0)

Project Structure

mcp-notification-server/
  server.py               FastMCP server -- all 8 tools defined here
  email_tool.py           SMTP email sending logic
  slack_tool.py           Slack Web API message sending
  teams_tool.py           Teams webhook message sending
  reminder_tool.py        In-memory reminder scheduler
  history_tool.py         Audit log reader with filtering
  config.py               Centralized environment variable config

  examples/
    langchain/
      langchain_agent.py  LangChain ReAct agent consuming this server
    langgraph/
      langgraph_agent.py  LangGraph ReAct agent consuming this server

  requirements.txt
  Dockerfile
  .env.example
  logs/                   Audit trail of all notifications sent

Quick Start

1. Install dependencies

git clone https://github.com/ChandraMohanBusam/mcp-notification-server
cd mcp-notification-server
pip install -r requirements.txt

2. Configure environment

cp .env.example .env

Fill in your values. Minimum required for email:

SMTP_USER=notifications@your-company.com
SMTP_PASSWORD=your-gmail-app-password
EMAIL_FROM=notifications@your-company.com

For Slack, add:

SLACK_BOT_TOKEN=xoxb-your-bot-token
SLACK_DEFAULT_CHANNEL=#general

For Teams, add:

TEAMS_WEBHOOK_URL=https://outlook.office.com/webhook/your-url

3. Run the server

uvicorn server:mcp --host 0.0.0.0 --port 8002

4. Connect to claude.ai (optional)

  1. Make the server publicly accessible via ngrok: ngrok http 8002
  2. In claude.ai: Settings > Integrations > Add MCP server
  3. URL: https://your-ngrok-url.ngrok.io/sse

Now you can say to Claude: "Send an email to team@company.com about the deployment."


Consuming from LangChain

from langchain.agents import initialize_agent, AgentType
from langchain_openai import ChatOpenAI
from langchain_mcp_adapters.tools import load_mcp_tools
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def run():
    async with streamablehttp_client("http://localhost:8002/mcp") as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Loads all tools from MCP server automatically
            tools = await load_mcp_tools(session)

            llm = ChatOpenAI(model="gpt-4o", temperature=0)
            agent = initialize_agent(
                tools, llm,
                agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
                verbose=True
            )

            result = await agent.arun(
                "Send an email to team@company.com that deployment 2026.3.0.71 succeeded"
            )
            print(result)

The key line is load_mcp_tools(session). LangChain reads the MCP server's tool manifest and automatically creates LangChain Tool objects. No manual tool definitions needed on the client side.

See the full example: examples/langchain/langchain_agent.py


Consuming from LangGraph

from langchain_openai import ChatOpenAI
from langchain_mcp_adapters.tools import load_mcp_tools
from langgraph.prebuilt import create_react_agent
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

async def run():
    async with streamablehttp_client("http://localhost:8002/mcp") as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()

            # Same tool loading as LangChain
            tools = await load_mcp_tools(session)

            llm = ChatOpenAI(model="gpt-4o", temperature=0)

            # LangGraph: create_react_agent instead of initialize_agent
            agent = create_react_agent(llm, tools)

            # LangGraph: ainvoke with messages list instead of arun
            result = await agent.ainvoke({
                "messages": [{"role": "user", "content":
                    "Send a Slack message to #deployments that 2026.3.0.71 is live, "
                    "then email team@company.com the same update."
                }]
            })
            print(result["messages"][-1].content)

See the full example with memory checkpointing: examples/langgraph/langgraph_agent.py


LangChain vs LangGraph: Key Differences

Both consume this MCP server identically via load_mcp_tools(). The difference is in the agent layer above.

LangChain ReAct LangGraph ReAct
Agent creation initialize_agent(tools, llm, ...) create_react_agent(llm, tools)
Invocation agent.arun(prompt) agent.ainvoke({"messages": [...]})
Memory/state Manual implementation Built-in checkpointer support
Human-in-loop Manual implementation Built-in interrupt support
Best for Simple conversational tasks Structured multi-step flows

Use LangChain when the task is straightforward and conversational. Use LangGraph when you need memory between turns, human approval checkpoints, or guaranteed step ordering.


Conversation Examples (via claude.ai)

"Send an email to team@company.com about the deployment"
"Post a Slack message to #alerts that the service is down"
"Send a Teams alert with red color that the database is unreachable"
"Remind me in 30 minutes via Slack to check the deployment logs"
"What reminders do I have scheduled?"
"Cancel reminder a1b2c3d4"
"Did the email to team@company.com go out successfully?"
"Show me failed notifications from today"

Notification Audit Log

All notifications are logged to logs/notifications.log:

2026-04-25 10:15:32 [INFO] [EMAIL]   SUCCESS | to=team@company.com | subject=Deployment Complete
2026-04-25 10:15:45 [INFO] [SLACK]   SUCCESS | channel=#deployments
2026-04-25 10:15:52 [INFO] [TEAMS]   SUCCESS | title=Deployment Success
2026-04-25 10:16:00 [INFO] [REMINDER] SCHEDULED | id=a1b2c3d4 | delay=30min | channel=slack
2026-04-25 10:46:01 [INFO] [REMINDER] FIRED | id=a1b2c3d4

The get_notification_history tool reads this log and answers natural language questions about it.


Architectural Context

This server is Approach B from the AI Deployment Agent.

In that project, email notification was implemented directly inside the deployment MCP server (Approach A). This works for a single agent. When multiple agents need notifications, this standalone server becomes the shared layer that all agents connect to.

Approach A (single agent): Notification logic lives inside each agent's MCP server.

Approach B (this repo): Notification logic lives in one shared MCP server. All agents connect to it as a dependency. One place to update, one audit log for all notifications across all agents.


Docker

docker build -t mcp-notification-server .
docker run -d \
  --env-file .env \
  -v $(pwd)/logs:/app/logs \
  -p 8002:8002 \
  mcp-notification-server

Gmail Setup

Gmail requires an App Password for SMTP access.

  1. Go to your Google Account
  2. Security > 2-Step Verification > App passwords
  3. Create a new app password for Mail
  4. Use the 16-character password as SMTP_PASSWORD in your .env

License

MIT License. Use freely, adapt to your needs, contributions welcome.

About

Reusable MCP notification server with email, Slack, Teams, and reminder tools. Consumed by LangChain and LangGraph agents. The shared notification layer in a multi-agent architecture.

Topics

Resources

License

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors