LangChain / LangGraph
Connect a LangChain or LangGraph agent (Python or JS) to SealGate using langchain-mcp-adapters, keeping a stable session per conversation so data-leak protection holds across every turn.
LangChain and LangGraph connect to SealGate through langchain-mcp-adapters' MultiServerMCPClient, which turns MCP tools into native LangChain tools. Your connection URL carries your API key, so no auth header is needed.
pip install langchain-mcp-adapters langgraph "langchain[openai]"import asyncio
import os
from langchain_mcp_adapters.client import MultiServerMCPClient
from langchain.agents import create_agent
async def main() -> None:
client = MultiServerMCPClient({
"sealgate": {
"transport": "streamable_http",
"url": os.environ["SEALGATE_MCP_URL"],
}
})
tools = await client.get_tools()
agent = create_agent("openai:gpt-5.6-luna", tools)
result = await agent.ainvoke({"messages": "List my available tools."})
print(result["messages"][-1].content)
asyncio.run(main())Set SEALGATE_MCP_URL to your connection URL, e.g. https://mcp.sealgate.ai/mcp/<your-api-key>/?client=langchain.
npm install @langchain/mcp-adapters @langchain/langgraph @langchain/core @langchain/openai langchainA server entry with only a url defaults to Streamable HTTP (with automatic SSE fallback). Disable the fallback to lock to the transport SealGate serves:
import { createAgent } from "langchain";
import { ChatOpenAI } from "@langchain/openai";
import { MultiServerMCPClient } from "@langchain/mcp-adapters";
const client = new MultiServerMCPClient({
mcpServers: {
sealgate: {
url: process.env.SEALGATE_MCP_URL!,
automaticSSEFallback: false,
},
},
});
const tools = await client.getTools();
const agent = createAgent({ model: new ChatOpenAI({ model: "gpt-5.6-luna" }), tools });
const res = await agent.invoke({
messages: [{ role: "user", content: "List my available tools." }],
});
console.log(res);
await client.close();Keep a stable session across turns to preserve data-leak protection
Send a stable x-sealgate-conversation-id header on every turn of the same conversation. That header is what keeps SealGate's data-leak protection intact across a multi-turn run: SealGate tracks lethal-trifecta risk per session, so if each turn looks like a brand-new session, that protection resets - and a later turn can leak data that the accumulated risk should have blocked.
Hosted clients (Claude Code, VS Code) send it automatically. For a custom LangChain or LangGraph agent, set the header on the server entry, keyed to your own conversation or thread id - and reuse that id on every turn:
"sealgate": {
"transport": "streamable_http",
"url": os.environ["SEALGATE_MCP_URL"],
"headers": {"x-sealgate-conversation-id": conversation_id},
}sealgate: {
url: process.env.SEALGATE_MCP_URL!,
automaticSSEFallback: false,
headers: { "x-sealgate-conversation-id": conversationId },
}Without a stable x-sealgate-conversation-id, each connection is treated as a fresh session that starts with empty risk state - so risk accumulated on an earlier turn won't be there to block a later exfiltration. The ?client= label is only a dashboard tag, not a session key. Use a unique id per conversation (a UUID is ideal); ids are scoped to your API key, so don't reuse one string for two different conversations.
Optional: the encrypted-secrets header
For servers with zero-knowledge-encrypted secrets, add a headers entry, alongside x-sealgate-conversation-id (only the http/sse transports honor runtime headers):
"sealgate": {
"transport": "streamable_http",
"url": os.environ["SEALGATE_MCP_URL"],
"headers": {
"x-sealgate-conversation-id": conversation_id,
"x-sealgate-secret-key": os.environ["SEALGATE_SECRET_KEY"],
},
}sealgate: {
url: process.env.SEALGATE_MCP_URL!,
automaticSSEFallback: false,
headers: {
"x-sealgate-conversation-id": conversationId,
"x-sealgate-secret-key": process.env.SEALGATE_SECRET_KEY!,
},
}