Orientation
How the bridge works
Keep one idea in mind and the rest follows: Hermes is the assistant, n8n is the operations team. Hermes understands what the lawyer wants, asks any missing questions, and picks the right tool. n8n runs the actual steps — reading email, OCRing PDFs, calling AI, writing to a database — and hands back a tidy JSON result that Hermes reads aloud in plain language.
The two talk over the Model Context Protocol (MCP). In n8n you build one "server" workflow whose MCP Server Trigger node publishes a URL. Each legal workflow is attached to that node as a callable tool. Hermes connects to the URL as an MCP client, sees the ten tools, and calls whichever one matches the request. Nothing about the automation lives inside Hermes — so you can rewrite a workflow in n8n without touching the agent.
If it involves judgement, wording, or talking to the lawyer → Hermes. If it involves moving data, calling an API, or waiting → n8n. Never put automation logic in the agent, and never put legal reasoning in a workflow.
Step 01
Prerequisites
Five minutes of checks before you start. Confirm each one:
| Requirement | Why | Check |
|---|---|---|
| Docker Desktop (or Engine + Compose) | Runs n8n in an isolated container | docker --version |
| Hermes Desktop Agent installed | The MCP client that will call your workflows | Opens and reaches its settings screen |
| Port 5678 free | n8n's editor and MCP endpoint bind here | Nothing else is using it |
| An AI provider key (optional) | Several workflows call an LLM for review/drafting | e.g. Anthropic or OpenAI key on hand |
| Gmail / Drive access (optional) | Intake and email workflows read from these | Account you can authorise in n8n |
The single-container setup below is meant for development and testing on your own machine. Client data protections, backups, HTTPS and access controls come later — see Toward production. Don't point it at live client matters yet.
Step 02
Run n8n in Docker
One volume to keep your work, one command to start the container. Everything n8n stores — workflows, credentials, and its encryption key — lives in the named volume, so it survives restarts and upgrades.
-
Create a persistent volume
Do this once. Your workflows and credentials are stored here, not inside the container.
terminaldocker volume create n8n_data
-
Start n8n
Maps the editor to
localhost:5678, mounts the volume, and sets your timezone so scheduled nodes behave. SwapAsia/Kolkatafor your own zone.terminal · macOS / Linuxdocker run -it --rm --name n8n -p 5678:5678 \ -e GENERIC_TIMEZONE="Asia/Kolkata" \ -e TZ="Asia/Kolkata" \ -e N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true \ -e N8N_RUNNERS_ENABLED=true \ -v n8n_data:/home/node/.n8n \ docker.n8n.io/n8nio/n8n
On Windows PowerShell, replace the trailing
\line-continuations with a backtick`, or paste it all on one line. -
Open the editor
Visit the address below, create your owner account, and you're in. Keep this browser tab open — you'll build every workflow here.
browserhttp://localhost:5678
-
(Optional) Prefer Docker Compose
If you'd rather manage n8n declaratively, save this as
compose.yamland rundocker compose up -d. Easier to restart and version-control.compose.yamlservices: n8n: image: docker.n8n.io/n8nio/n8n restart: unless-stopped ports: - "5678:5678" environment: - GENERIC_TIMEZONE=Asia/Kolkata - TZ=Asia/Kolkata - N8N_RUNNERS_ENABLED=true - N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS=true volumes: - n8n_data:/home/node/.n8n volumes: n8n_data:
Pull the newest image and restart: docker pull docker.n8n.io/n8nio/n8n, then stop and re-run the container (or docker compose pull && docker compose up -d). Your volume keeps everything intact.
Step 03
Connect Hermes over MCP
You'll build one small "server" workflow that acts as the front door for all ten tools. n8n's MCP Server Trigger node exposes a URL; Hermes connects to that URL and discovers every attached tool automatically.
-
Create the MCP server workflow
New workflow → name it
Hermes MCP Gateway. Add a node and search for MCP Server Trigger. This is the only trigger this workflow needs. -
Turn on authentication
In the node, set Authentication → Bearer and generate a credential with a long random token. Every request from Hermes must carry this token, so no stray process on your machine can call your tools.
generate a tokenopenssl rand -hex 32
-
Copy the endpoint URL
The node shows a Test URL and a Production URL (a path like
/mcp/<random-id>). Use the Test URL while building; switch to the Production URL once the workflow is activated. It looks like this:mcp endpointhttp://localhost:5678/mcp/<your-generated-path>
-
Point Hermes at it
In Hermes' settings, add an MCP server. Give it the URL and the bearer token. Save, then reconnect — Hermes should report the tools it discovered (none yet; you'll add them next).
hermes · mcp server config{ "name": "n8n-legal", "transport": "sse", "url": "http://localhost:5678/mcp/<your-path>", "headers": { "Authorization": "Bearer <your-token>" } }If Hermes runs in its own containerUse
http://host.docker.internal:5678instead oflocalhostso the agent can reach n8n across the container boundary.
Step 04
The workflow pattern
Every one of the ten workflows follows the same shape, so once you build one the rest are variations. Each tool is a separate sub-workflow; the gateway just exposes them.
A · Build the sub-workflow
New workflow, starting with an Execute Sub-workflow Trigger. Define its input fields (its "arguments"). Add the processing nodes. End by returning a single structured JSON object.
B · Expose it on the gateway
In Hermes MCP Gateway, add a Custom n8n Workflow Tool node, connect it to the MCP Server Trigger, and point it at the sub-workflow. Its name and description are what Hermes reads when choosing a tool — write them for the lawyer, not the engineer.
Two rules that keep this maintainable
One workflow, one job. Resist the urge to build a single "legal automation" monster. Small, named workflows are easier to test, reuse, and reason about.
Always return structured JSON — and never a raw error. Hermes turns your JSON into a sentence. If something breaks, hand back a friendly failure object, not a 500.
Good failure
{
"status": "failed",
"reason": "Court API unavailable"
}Hermes says
// spoken to the lawyer
"The court system is
temporarily unavailable.
Please try again shortly."Hermes picks a tool purely from its name and description. "Reviews an inbound contract PDF and flags risky clauses" beats "contract_review_v2" every time. Be concrete about what goes in and what comes out.
Step 05
The ten workflows
Build them in order — the first few are simple and teach the pattern; the later ones layer in OCR, retrieval, and long-form generation. For each: the phrase a lawyer might say, the pipeline of nodes, the JSON in and out, and expandable build notes.
Client Intake
Turn a new enquiry into a client, a matter, folders, and a welcome email.
Input
{
"client_name": "ABC Limited",
"matter_type": "Commercial",
"email": "gc@abc.co"
}Output
{
"status": "success",
"matter_id": "MAT-1002",
"assigned_to": "R. Shah",
"folder_url": "..."
}Build notes
- Sub-workflow trigger with fields:
client_name,matter_type,email. - Set node generates the matter ID (e.g. prefix + counter from a Postgres/Sheets row).
- Postgres (or Google Sheets) insert to create client + matter records.
- Google Drive "Create folder" for the matter workspace.
- Gmail send welcome email; Set node assembles the final JSON.
Contract Triage
Classify an inbound contract, flag its risk lane, and route it with an SLA.
Input
{
"document_url": "...",
"counterparty": "Vendor Co"
}Output
{
"status": "success",
"doc_type": "NDA",
"lane": "self_serve",
"risk": "Low",
"sla_hours": 24
}Build notes
- Download the file (HTTP Request or Drive), then Extract from File for text.
- AI node with a strict classification prompt returning
doc_type,risk, and rationale as JSON. - Switch node maps risk → lane (self-serve / legal review / escalate) and SLA hours from your playbook thresholds.
- It routes only — it never drafts or approves. Escalations get a notification to counsel.
Legal Notice Draft
Read an incoming notice and prepare a first-draft response grounded in similar past notices.
Input
{
"document_url": "...",
"matter_id": "MAT-1002"
}Output
{
"status": "success",
"draft_url": "...",
"precedents_used": 3,
"summary": "Reply drafted"
}Build notes
- OCR the notice (an OCR/vision node or AI vision) into clean text.
- AI node extracts parties, claims, and deadlines as structured fields.
- Retrieve similar past notices from your vector store / IntelliVault to ground the draft.
- AI node drafts the reply; save it to the matter folder and notify the responsible lawyer.
- Always returns a draft for human review — never sends anything.
Hearing Preparation
Assemble a hearing brief: where the matter stands, points to argue, documents and authorities needed.
Input
{
"matter_id": "MAT-1002",
"hearing_purpose": "interim relief"
}Output
{
"status": "success",
"brief_url": "...",
"authorities": 4,
"open_items": 2
}Build notes
- Fetch all matter documents and metadata (Postgres + Drive).
- Build a chronological timeline with a Code or Sort node.
- Retrieve relevant precedents/authorities from your research store.
- AI node assembles hearing notes + a readiness checklist; save as a document.
- Prep for counsel — it lays out options; counsel decides strategy.
Legal Research
Answer a research question across judgments, legislation, and the firm's own past matters.
Input
{
"question": "limitation for
dishonoured cheque suit",
"jurisdiction": "India"
}Output
{
"status": "success",
"report_url": "...",
"sources": 7,
"confidence": "Medium"
}Build notes
- Fan out three searches in parallel: case law source, legislation source, internal matter store.
- Merge the results, then an AI node synthesises with citations and a confidence flag.
- Generate a report document; return its URL and source count.
- Surface citations so the lawyer can verify — never present unsourced conclusions as settled.
Client Email Processing
Triage the inbox: classify each message, attach it to a matter, and notify the right lawyer.
Input
{
"since": "today",
"label": "Clients"
}Output
{
"status": "success",
"processed": 14,
"matched": 11,
"needs_review": 3
}Build notes
- Gmail node reads messages since the given time / label.
- Loop over each: AI node classifies (query, document, urgent, spam) and extracts attachments.
- Match sender/subject to a matter; unmatched items go to a "needs review" bucket.
- Notify the responsible lawyer and archive; return the tallies.
Invoice Automation
Read an inbound invoice, validate it, update accounting, and flag anything off.
Input
{
"document_url": "...",
"matter_id": "MAT-1002"
}Output
{
"status": "success",
"amount": "12,400",
"valid": true,
"flags": []
}Build notes
- Extract invoice fields with an AI / OCR node (vendor, amount, tax, due date).
- IF nodes validate totals, tax, and duplicates against your records.
- Write to your accounting sheet/system; raise flags for mismatches.
- Notify finance and return the parsed record.
Conflict Check
Screen a prospective matter against existing and former clients before it's opened.
Input
{
"prospective_client": "XYZ Corp",
"adverse_parties": ["ABC Limited"]
}Output
{
"status": "success",
"conflict": "potential",
"basis": "ABC is a current client",
"routed_to": "compliance"
}Build notes
- Normalise party names (strip suffixes, alias table) with a Code node.
- Query client and matter tables for direct adversity, current/former, and positional conflicts.
- Classify status: clear / potential / conflict — with the specific basis.
- It never auto-clears. Any match routes to a human; a clean result still records the check.
Document Drafting
Generate a long-form legal document from a matter and a document type, section by section.
Input
{
"doc_type": "shareholders_agreement",
"matter_id": "MAT-1002",
"instructions": "2 founders,
vesting over 4 years"
}Output
{
"status": "success",
"draft_url": "...",
"sections": 11,
"words": 4200
}Build notes
- Look up the document-type descriptor (sections, clauses) from your prompt library.
- Loop over sections — one AI call each — so long documents don't blow the context window.
- Merge sections into one document; write to Drive as an editable draft.
- This is the long-form generation engine: keep prompts version-controlled per document type.
GST Notice Analysis
Read a GST notice, classify it, extract the demand, and outline a response strategy.
Input
{
"document_url": "...",
"gstin": "24AABC..."
}Output
{
"status": "success",
"notice_type": "ASMT-10",
"demand": "3,20,000",
"reply_due": "2026-08-01"
}Build notes
- OCR the notice, then an AI classification node maps it to a notice type using your JSON prompt library.
- Extract the demand amount, period, and reply deadline as structured fields.
- A Code node computes days remaining and urgency.
- Generate a short response outline; return the key facts for Hermes to summarise.
If ten feels like a lot for day one, build 01, 02, 03, 05 and 06 first — client intake, contract triage, notice draft, research and email processing cover most daily work and teach every technique the others reuse.
Step 06
Test & troubleshoot
Test each layer in order
-
Test the sub-workflow alone
In the sub-workflow, click Execute and pass sample input. Confirm it returns clean JSON before wiring it to anything.
-
Test the tool over MCP
Activate the gateway workflow, then ask Hermes to run the tool with a simple request. Watch the Executions tab in n8n to see it fire.
-
Test the whole sentence
Say it the way a lawyer would. Check that Hermes picks the right tool and reads the result back naturally.
Common issues
| Symptom | Likely cause | Fix |
|---|---|---|
| Hermes sees no tools | Using the Test URL on an inactive workflow, or wrong path | Activate the gateway and switch Hermes to the Production URL |
401 Unauthorized | Token mismatch | Re-copy the bearer token into Hermes' config exactly |
| Connection drops mid-call | A reverse proxy buffering the SSE stream | Disable proxy buffering on the MCP endpoint (not relevant for plain localhost) |
| Agent in a container can't reach n8n | Using localhost across containers | Use host.docker.internal:5678 |
| Tool never gets picked | Vague tool name/description | Rewrite the description in the lawyer's language |
Step 07
Toward production
Once the lab works, the gap to something client-safe is mostly operational, not architectural — the Hermes ↔ MCP ↔ n8n shape stays the same. Before real matters touch it:
- Switch off SQLite for Postgres and set a persistent, backed-up database — the single-container store is fine for a lab, not for client data.
- Terminate TLS in front of n8n (Caddy or nginx) so the MCP endpoint runs over HTTPS, and keep the bearer token in a secret store.
- Keep every credential inside n8n. Hermes should never hold API keys — it holds only the MCP URL and token.
- Log every execution — user, matter, workflow, model, cost, duration, outcome — for audit and troubleshooting.
- Version-control your prompts and workflow exports so drafting and classification behaviour is reproducible.
- Keep humans in the loop where it counts: triage routes, conflict checks flag, drafts stay drafts. The workflows prepare; a lawyer decides.
This same gateway can later sit behind VajraGrid, with IntelliVault supplying context and other engines (Python services, Celery pipelines) joining alongside n8n. The lawyer keeps talking only to Hermes while the execution layer underneath evolves.