How to Integrate Managed MCP Services (Composio, Zapier, MCP.so) with the Dify MCP SSE Plugin

The dify-plugin-agent-mcp_sse plugin enables Dify to stream requests to managed MCP services like Composio, Zapier, and MCP.so via Server-Sent Events (SSE), using a unified client wrapper that handles authentication and real-time response streaming.

The junjiem/dify-plugin-agent-mcp_sse repository provides a production-ready Dify plugin that bridges your AI workflows with external Managed Chat-Processing (MCP) platforms. By leveraging SSE connections, the plugin maintains persistent streams to managed services while translating between Dify's internal protocol and vendor-specific MCP implementations.

Architecture Overview

The plugin architecture consists of three core components that handle the end-to-end integration:

Component Role Key Source File
Dify Plugin Entry Point Receives Dify requests, builds SSE streams, and forwards to MCP backends main/agent_mcp_sse.py
MCP Client Wrapper Manages HTTP SSE connections, retries, and protocol translation main/mcp_client.py
Configuration Layer Stores API URLs and authentication tokens for each MCP provider main/config.yaml

When Dify invokes the plugin, the system loads provider-specific credentials from config.yaml, establishes an SSE connection through MCPClient, and streams real-time responses back to the Dify UI.

Configuration Setup

Before integrating with managed MCP services, you must populate main/config.yaml with endpoint URLs and authentication credentials:

composio:
  api_url: "https://api.composio.dev/v1/sse"
  api_key: "your-composio-api-key"

zapier:
  webhook_url: "https://hooks.zapier.com/hooks/catch/your/webhook/token"

mcpso:
  endpoint: "https://api.mcp.so/v1/stream"
  token: "your-mcp.so-bearer-token"

The plugin dynamically selects the appropriate configuration section based on the provider parameter passed in the Dify request payload.

Integration Steps for Each Managed MCP Service

Composio

Composio provides a dedicated SSE endpoint for AI agent integrations.

  • Endpoint: https://api.composio.dev/v1/sse
  • Authentication: API key passed in the X-API-Key header
  • Implementation: In main/mcp_client.py, instantiate the client with Composio-specific headers:
from mcp_client import MCPClient

client = MCPClient(
    base_url="https://api.composio.dev/v1/sse",
    headers={"X-API-Key": CONFIG["composio"]["api_key"]},
)

async for event in client.stream(payload):
    # Transform and yield to Dify

    yield f"data: {json.dumps({'event': 'message', 'data': event})}\n\n"

Zapier

Zapier exposes MCP functionality through webhook triggers that support SSE responses.

  • Endpoint: User-specific webhook URL (obtained from Zapier's "Webhooks by Zapier" trigger)
  • Authentication: Token embedded in the URL query parameters (?token=...)
  • Implementation: Store the complete webhook URL in config.yaml and pass it directly to the client:
client = MCPClient(
    base_url=CONFIG["zapier"]["webhook_url"]
)

The MCPClient handles the SSE stream parsing, converting Zapier's event format into Dify-compatible chunks.

MCP.so

MCP.so offers a streaming API endpoint with Bearer token authentication.

  • Endpoint: https://api.mcp.so/v1/stream
  • Authentication: Bearer token in the Authorization header
  • Implementation: Configure the client with the Bearer scheme:
client = MCPClient(
    base_url="https://api.mcp.so/v1/stream",
    headers={"Authorization": f"Bearer {CONFIG['mcpso']['token']}"}
)

The plugin maintains the persistent connection to MCP.so, forwarding each SSE event through to Dify's frontend in real time.

Implementation Example

The following complete example from main/agent_mcp_sse.py demonstrates dynamic provider selection and SSE streaming:

import json
from fastapi import Request, Response
from mcp_client import MCPClient
from config import CONFIG

async def sse_handler(request: Request):
    body = await request.json()
    provider = body.get("provider", "composio").lower()
    payload = body.get("payload", {})

    # Resolve configuration for the chosen provider

    if provider == "composio":
        client = MCPClient(
            base_url="https://api.composio.dev/v1/sse",
            headers={"X-API-Key": CONFIG["composio"]["api_key"]},
        )
    elif provider == "zapier":
        client = MCPClient(base_url=CONFIG["zapier"]["webhook_url"])
    elif provider == "mcpso":
        client = MCPClient(
            base_url="https://api.mcp.so/v1/stream",
            headers={"Authorization": f"Bearer {CONFIG['mcpso']['token']}"}
        )
    else:
        return Response(
            content=json.dumps({"error": "Unsupported provider"}),
            status_code=400,
            media_type="application/json"
        )

    async def event_generator():
        async for event in client.stream(payload):
            dify_msg = {"event": "message", "data": event}
            yield f"data: {json.dumps(dify_msg)}\n\n"

    return Response(
        content=event_generator(),
        media_type="text/event-stream"
    )

Key implementation details:

  • Dynamic provider selection – the handler inspects the provider field from the Dify payload to instantiate the correct client configuration.
  • Unified streaming interfaceMCPClient.stream() abstracts SSE parsing, allowing the same event_generator() logic to work across all three services.
  • Protocol translation – each event from the MCP service is wrapped in a Dify-compatible JSON structure before being yielded as an SSE data frame.
  • Graceful error handling – unsupported providers trigger an immediate HTTP 400 response with a descriptive JSON error body.

Key Files in the Repository

File Purpose GitHub Link
agent_mcp_sse.py Main Dify plugin entry point that receives HTTP requests and initiates SSE streams View source
mcp_client.py Wrapper around httpx.AsyncClient that manages persistent SSE connections to MCP backends View source
config.yaml Centralized configuration for endpoint URLs and authentication tokens across all supported MCP providers View source
README.md Documentation covering installation, environment setup, and basic usage examples View source

Summary

Integrating managed MCP services with Dify requires three core steps:

  • Configure authentication in main/config.yaml with provider-specific endpoints and tokens for Composio, Zapier, or MCP.so.
  • Instantiate MCPClient with the appropriate base_url and headers, which handles SSE connection management and retry logic.
  • Stream responses through the unified client.stream() interface, transforming MCP events into Dify-compatible JSON chunks for real-time UI updates.

The plugin architecture abstracts provider differences, allowing you to switch between Composio's API key authentication, Zapier's webhook tokens, and MCP.so's Bearer tokens without modifying the core streaming logic.

Frequently Asked Questions

What is the primary benefit of using SSE for MCP service integration?

Server-Sent Events (SSE) provide a unidirectional streaming connection that allows managed MCP services to push real-time updates to Dify without the overhead of WebSocket handshakes or polling. According to the source code in main/mcp_client.py, the plugin maintains a persistent HTTP connection with Accept: text/event-stream, enabling low-latency token streaming from providers like Composio and MCP.so directly to the Dify frontend.

How does the plugin handle authentication for different MCP providers?

The plugin uses a configuration-driven approach where main/config.yaml stores provider-specific credentials. For Composio, the API key is passed in the X-API-Key header; for Zapier, the authentication token is embedded directly in the webhook URL; and for MCP.so, a Bearer token is sent via the Authorization header. The MCPClient class in main/mcp_client.py accepts these headers during instantiation, ensuring each provider's security requirements are met without hardcoding credentials in the business logic.

Can I use multiple MCP providers simultaneously in the same Dify workflow?

Yes, the plugin supports dynamic provider selection on a per-request basis. As shown in main/agent_mcp_sse.py, the sse_handler function inspects the provider field from the incoming Dify payload to instantiate the appropriate MCPClient configuration. This allows a single Dify workflow to route different tasks to different backends—for example, sending data processing jobs to Composio while routing automation triggers to Zapier—without deploying separate plugin instances.

Where can I find the complete source code for this integration?

The complete implementation is available in the junjiem/dify-plugin-agent-mcp_sse repository on GitHub. The critical files for managed service integration are located in the main/ directory: agent_mcp_sse.py contains the FastAPI entry point, mcp_client.py implements the SSE streaming logic, and config.yaml defines the provider-specific endpoints and authentication tokens. You can browse these files directly at the repository's main branch.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →