Hermes Kernel MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Hermes Kernel MCP Serverlist all tools"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Hermes Kernel v2
An async-first, event-driven AI Operating System kernel — Clean Architecture, plugin-extensible, MCP-native.
Status: v2.17.0 · 753 passed, 3 skipped, 92% coverage (Python 3.11+). All phases P0–P5 + extensions A/A2/B/C/D/E/F + ADR-007..030 + CI axis-gate delivered.
What is this?
Hermes Kernel v2 is the core runtime of an AI Operating System. It provides the minimal, well-factored primitives that higher layers (knowledge pipeline, agents, integrations) build on:
Domain — pure Pydantic entities (documents, chunks, tools, tasks, events, capabilities, agents), JSON/MCP-serialisable, zero framework coupling.
Event bus — async, fire-and-forget
publish+wait_forsync barrier, fault-contained per handler.Registries — plugins, tools, capabilities, agents (async lock + sync fast-path for construction).
Executor — capability-driven
Taskstate machine over the bus.Workspace — multi-workspace registry (single-tenant today).
Plugins — fault-tolerant loader + a declarative SDK (
@agent,@tool,@on_event,@capability).MCP — bidirectional Model Context Protocol (client consumes external servers; server exposes kernel tools), stdio JSON-RPC 2.0, no external MCP lib.
Architecture follows Clean Architecture with a CI-enforced inward dependency
axis (import-linter). See docs/adr/.
Related MCP server: Agentforce MCP Integration Server
Knowledge Pipeline (P2)
Raw files become a queryable knowledge graph through five independent, event-driven, workspace-scoped stages — each subscribes to the previous stage's event and publishes its own (no direct coupling). See ADR-004.
┌───────────────┐ document.scanned ┌────────────────┐ document.parsed
│ FileScanner │ ──────────────────▶ │ DocumentParser │ ─────────────────┐
└───────────────┘ └────────────────┘ │
▼
┌────────────────┐ chunk.embedded ┌───────────────┐ chunk.created ┌──────────────────┐
│ KnowledgeGraph │ ◀──────────────── │ ChunkEmbedder │ ◀────────────── │ DocumentChunker │
└───────┬────────┘ └───────────────┘ └──────────────────┘
│ graph.updated
▼
(node_id, edges, workspace_id)Stage | Does | Optional dep |
| polling watch, emits scanned files | — (no watchdog) |
| extract text by MIME type |
|
| sliding-window chunks w/ overlap | — |
| vector embeddings |
|
| cosine-similarity linking, workspace-isolated | — |
Heavy deps are lazily imported and optional; the default path (hash embeddings,
text parsing) is stdlib-only. End-to-end verified in
tests/test_integration_p2.py (real .md → 10 nodes, 8 edges).
Persistence & Multi-tenancy (P5)
The kernel is multi-tenant: users authenticate, operations are gated by RBAC,
and state survives restart in a workspace-isolated store. All stdlib
(hashlib, sqlite3) — no heavy deps. See
ADR-005.
Layer | Module | Responsibility |
Auth |
|
|
RBAC |
|
|
Persistence |
| SQLite async CRUD, workspace-isolated JSON store |
RBAC is a guard (require_permission before a registry call), not a
wrapper — see tests/test_rbac.py. Persistence composes with WorkspaceRegistry
(save/load), KnowledgeGraph (persist/load) and FileScanner (DB-backed
de-duplication) without rewriting them.
Extensions: SSE, Streamable HTTP, Retrieval, CLI (post-v0.7.0)
A — SSE transport for MCP (mcp/server_sse.py)
MCPServerSSE bridges the stdio MCPServer JSON-RPC core to the SSE transport:
GET /sse opens a text/event-stream and emits an endpoint event;
POST /messages/?sessionId=... carries JSON-RPC, responses stream back. Pure
stdlib (http.server + a dedicated asyncio loop) — no FastAPI/uvicorn.
srv = MCPServerSSE(tool_registry, event_bus)
srv.set_handler("echo", lambda a: f"got:{a.get('v')}")
srv.start(host="127.0.0.1", port=8080) # GET /sse + POST /messages/A2 — Streamable HTTP transport for MCP (mcp/server_streamable.py)
The modern MCP HTTP shape (see ADR-008):
POST /mcp/v1/messages carries JSON-RPC and returns the response in the POST
body (HTTP 200); GET /mcp/v1/events is a server→client SSE stream for
notifications. Sessions use the Mcp-Session-Id header (not a query param),
and JSON-RPC batches (requests: [...]) are aggregated. Pure stdlib.
Durable sessions (resumable): pass a PersistenceRegistry to the
constructor. Every server→client SSE frame is persisted (per-session workspace
mcp:<session_id>) and replayed on reconnect when the client sends a
Last-Event-ID header — surviving disconnects and (with a file-backed store) a
full server restart.
from kernel.persistence import PersistenceRegistry
srv = MCPServerStreamable(tool_registry, event_bus,
persistence=PersistenceRegistry(db_path="mcp.db"))
srv.set_handler("echo", lambda a: f"got:{a.get('v')}")
srv.start(host="127.0.0.1", port=8080) # POST /mcp/v1/messages + GET /mcp/v1/eventsB — KnowledgeRetrievalService (kernel/retrieval.py)
Durable, workspace-scoped vector search with pluggable backends (ADR-009).
from kernel.retrieval import KnowledgeRetrievalService
from kernel.retrieval_backends import FaissBackend
svc = KnowledgeRetrievalService(
persistence, bus,
backend=FaissBackend(persist_dir=".hermes/faiss", embedding_dim=384)
)
await svc.index_and_persist(node)
top = await svc.query(embedding, workspace_id="ws1", top_k=5)Backend | Class | Use case | Install |
Memory (default) |
| Small corpora, zero-dep | — |
Faiss |
| Large corpora, fast ANN |
|
SQLite-VSS |
| Medium corpora, SQLite-native |
|
Backends are swappable at construction time; the public API
(query(embedding, workspace_id, top_k)) never changes.
C — Plugin SDK CLI (plugins/sdk/cli.py)
A hermes console script (installed via [project.scripts]):
hermes plugin init myplugin # scaffold myplugin.py + plugin.yaml
hermes plugin watch ./plugins # hot-reload changed modules (polling, no watchdog)
hermes plugin list # list loaded plugins (name, version, caps, status)
hermes plugin validate ./myplugin # static check: manifest + compile + (--strict) deps
hermes plugin disable myplugin # unload from sys.modules + emit plugin.disabled eventThe list / disable commands drive the kernel's own PluginRegistry
(kernel/registry.py) — there is exactly one registry. validate runs the
PluginValidator (manifest schema → py_compile → dependency resolution) with
no plugin execution. See ADR-010.
D — Desktop Control builtin plugin (plugins/builtin/desktop_control/)
Exposes host mouse / keyboard / screenshot control as kernel Tools under the
hermes.desktop capability (see ADR-011). Optional deps are installed via
the desktop extra:
pip install 'hermes-kernel-v2[desktop]'Tool | Params | Returns |
|
|
|
|
|
|
|
|
|
|
|
|
| `region: list[int] | None = None` |
Design: DesktopControlPlugin(BasePlugin); every tool is async and offloads
the blocking pyautogui call via asyncio.to_thread (event loop never blocked).
load() raises RuntimeError on unsupported platforms or missing deps. Tools
are registered into ToolRegistry via register_tools(tr) after load()
(import-side-effect free — no global SDK state needed).
E — MCP Streamable HTTP hardening (mcp/server_streamable.py)
Two durability / interoperability hardenings on top of ADR-008 (see ADR-012):
Session TTL / eviction.
MCPServerStreamable(..., session_ttl=86400, evict_interval=3600)starts a background task that deletes persistedMcpSessionEventrows older thansession_ttlfrom eachmcp:<session_id>workspace (file-backed logs no longer grow unbounded).session_ttl=0disables eviction.Mcp-Protocol-Versionnegotiation. BothPOST /mcp/v1/messagesandGET /mcp/v1/eventsread the client'sMcp-Protocol-Versionheader. A match (or its absence — legacy client) is accepted and the server echoes its version on every response; a mismatch yields426 Upgrade Requiredadvertising the supported version. Default server version:2024-11-05.
F — Human Emulation Layer (plugins/builtin/human_emulation/, ADR-013)
Autonomous, human-like automation (browse sites, click, type) when the user is
away. Builtin plugin exposing 8 Tools under hermes.human.browser /
hermes.human.input:
BrowserAgent— async Playwright wrapper (visible browser):browser_start/navigate/click/type(human WPM + rare typos) /screenshot/close.InputSimulator— pyautogui with human-like micro-delays + occasional typos;FAILSAFE=True(cursor-to-corner aborts).HumanProfiledomain entity — the "digital twin" (typing speed, delays, screen resolution, user agent).BrowserSession+ActionLogentities give a full audit trail (workspace-isolated, ADR-007).
Optional deps behind the [human] extra (playwright, pyautogui); the kernel
imports cleanly without them (lazy import + clear RuntimeError).
Quick start
# 1. create / activate a Python 3.11+ virtualenv, then install
python -m pip install -e .
# 2. run the test suite
python -m pytest tests/ -v
# 3. run with coverage
python -m pytest tests/ --cov=kernel --cov=plugins --cov=mcp --cov-report=term-missingExpected: 209 passed, 3 skipped (sqlite-vss has no Windows wheels → 3 retrieval-backend tests skip; they pass on Linux).
Note: always invoke pytest as
python -m pytestso it resolves against the active venv interpreter (a barepip/pytestmay bind to a different Python).
Repository layout
hermes-kernel-v2/
├── kernel/ # core (domain, bus, registry, capability, executor, workspace, retrieval)
├── plugins/
│ ├── base.py # BasePlugin ABC
│ ├── loader.py # fault-tolerant plugin loader
│ ├── sdk/ # declarative authoring SDK (@agent/@tool/@on_event/@capability)
│ └── builtin/ # example plugins (filesystem)
├── mcp/ # client.py, server.py, server_sse.py, server_streamable.py, tools.py
├── tests/ # 174 tests across 17 suites
├── docs/
│ ├── adr/ # architectural decision records
│ └── roadmap.md # phase status + coverage
└── pyproject.tomlArchitecture
Decisions are recorded as ADRs:
ADR-001 — Kernel Architecture — layers, Clean Architecture, async/lock, event-driven.
ADR-002 — Plugin System —
BasePlugin, loader,plugin.yamlmanifest, Plugin SDK.ADR-003 — MCP Integration — MCP client/server,
MCPToolAdapter.ADR-004 — Knowledge Pipeline — 5 event-driven stages, workspace isolation, similarity linking.
ADR-005 — Multi-tenancy — Auth (P5.1), RBAC (P5.2), Persistent Storage (P5.3).
ADR-007 — Workspace Isolation — formal data-isolation contract (persistence, graph, retrieval, scanner, RBAC).
ADR-008 — Streamable HTTP Transport — POST /mcp/v1/messages + GET /mcp/v1/events,
Mcp-Session-Idheader, batches.ADR-009 — Retrieval Backends — Memory / Faiss / SQLite-VSS pluggable backends behind a stable API.
ADR-010 — Plugin CLI UX —
list/validate/disabledriving the singlePluginRegistry.ADR-011 — Desktop Control — builtin
DesktopControlPluginexposing mouse/keyboard/screenshot ashermes.desktopTools (lazypyautogui/Pillow, async, platform-guarded).ADR-012 — MCP Streamable HTTP hardening —
McpSessionEventTTL eviction (background task) +Mcp-Protocol-Versionnegotiation (426 on mismatch).ADR-013 — Human Emulation Layer —
plugins.builtin.human_emulation: PlaywrightBrowserAgent+ pyautoguiInputSimulator+HumanProfile/BrowserSession/ActionLogentities.ADR-016 — Agent/Plugin Unification —
BaseAgentasync lifecycle +AgentRuntime, unifiedArtifact(format/provenance/content: Any),CapabilityExecutor(namespaced dispatch →Artifact).ADR-017 — Event Platform + Desktop Agent Vision —
kernel/events.py(DomainEvent extends Event + EventStore append-only + CQRS Command/Query Bus),DesktopAgent(BaseAgent)event-driven,DesktopVision(OCR + element detection),CapabilityExecutor.register_agent.ADR-018 — Capability Handler Auto-Discovery —
kernel/discovery.py+CapabilityExecutor.autodiscover(instances): reflects over loaded plugin/agent instances and wires their capabilities (no plugin import, axis clean). Replaces manual bootstrap wiring.ADR-019 — Workflow Runtime Foundation —
kernel/workflow.py(WorkflowEnginestate machine: retry/backoff, reverse-order compensation, human-approval PAUSE, input-mapping from prior steps),kernel/planner.py(goal→Workflow),Workflowdomain model replaces the stub + activates deadTask.workflow_id. 23 tests.ADR-020 — Execution Sandbox —
kernel/sandbox.py(Sandbox.runsoft timeout/resource enforcement,TimeoutGuard,ResourceMonitorvia optionalpsutil); optional integration intoAgentRuntime/WorkflowEngine. 17 tests.ADR-021 — Health & Recovery —
kernel/health.py(HealthMonitorliveness probes,DeadLetterQueuefor failed work,CircuitBreakerper-capability state machine,RecoveryEngineauto-restart/escalation); optional integration intoAgentRuntime/WorkflowEngine/CapabilityExecutor(backward-compatible). 40 tests.ADR-022 — Behavior Engine —
plugins/builtin/desktop_control/behavior.py(BehaviorEngine: Bezier mouse curves + overshoot, scroll momentum, WPM typing rhythm with typos, gaze fixation + reading saccades/regressions) +human_profile.py(HumanProfileStoreCRUD + SQLite); optional integration intoDesktopAgent(desktop.click/type/scroll/read),UIElement.center*for targeting. 35 tests.ADR-023 — Swarm / Teams — multi-agent orchestration + distributed health:
kernel/swarm.py(SwarmCoordinator: create/join/leave, Bully leader election, heartbeat + suspicion/failure, capability-aware least-load delegation),kernel/distributed_health.py(DistributedHealthMonitor),kernel/team_manager.py(TeamManager),kernel/swarm_store.py(SwarmStorein-memory + SQLite); 8 swarm events; optional backward-compatible integration intoAgentRuntime/WorkflowEngine/CapabilityExecutor. 49 tests.ADR-024 — Dynamic Planner — adaptive replanning + risk-aware execution:
kernel/dynamic_planner.py(DynamicPlanner: DAG toposort, retry w/ exponential backoff, rule-based replan for 5 triggers + optional LLM shim,risk_assess),kernel/plan_store.py(PlanStorein-memory + SQLite), 6 planner events,WorkflowEngine.execute_adaptiveSwarmCoordinator.rebalance_load. 39 tests.
ADR-025 — Knowledge Graph & Semantic Memory — semantic memory:
kernel/semantic_graph.py(Entity/Relation/KnowledgeGraph models),kernel/knowledge_graph.py(KnowledgeGraphEngine: entities, relations, neighbor/path queries,similarvia injected embedding or Jaccard, rule-basedrun_inference),kernel/graph_store.py(SQLite), 6 KG events,AgentRuntime.remember/recall+WorkflowEngine.execute_with_context. 46 tests.ADR-026 — Plugin Marketplace & Multi-node —
kernel/marketplace_domain.py(PluginPackage/CatalogEntry/NodeInfo models),kernel/marketplace.py(PluginMarketplace: discover via injected http_client, install/uninstall, checksum+dependency validation,register_local),kernel/cluster.py(ClusterManager: join/leave, leader election, broadcast),kernel/marketplace_store.py(SQLite), 5 events,AgentRuntime.install_capability+WorkflowEngine.discover_plugins. 38 tests.
Roadmap
See docs/roadmap.md for full phase status.
Phase | Name | Status |
P0 | Kernel Core | ✅ |
P1 | Runtime + Capability | ✅ |
P2 | Knowledge Pipeline | ✅ |
P3 | MCP + SDK | ✅ |
P4 | MCP Server | ✅ |
P5 | Multi-tenancy | ✅ |
A | SSE transport | ✅ |
B | KnowledgeRetrievalService | ✅ |
C | Plugin SDK CLI | ✅ |
D | ADR-007 Workspace Isolation | ✅ |
Authoring a plugin
from plugins.sdk import sdk, configure_sdk
from kernel.bus import EventBus
from kernel.registry import AgentRegistry, ToolRegistry
from kernel.capability import CapabilityRegistry
tr = ToolRegistry()
configure_sdk(
agent_registry=AgentRegistry(),
tool_registry=tr,
capability_registry=CapabilityRegistry(tr),
bus=EventBus(),
)
@sdk.agent(name="researcher", capabilities=["hermes.search"])
class Researcher:
@sdk.tool(name="web_search", capability="hermes.search",
schema={"type": "object", "properties": {"q": {"type": "string"}}})
async def search(self, q: str) -> list:
...
Researcher() # registration happens on constructionCI / Dependency axis gate
GitHub Actions (.github/workflows/ci.yml) runs on every push/PR to main,
matrix Python 3.11 + 3.12. Three gates, in order:
Gate | Command | Threshold |
Axis (Clean Architecture) |
| zero violations |
Tests |
| 228 passed, 0 failed |
Coverage |
| ≥ 85% |
The axis contract (in [tool.tach] in pyproject.toml):
kernel.domain → [] (shared pydantic contract, leaf)
kernel → [kernel.domain]
plugins → [kernel, kernel.domain]
plugins.builtin.desktop_control → [kernel, kernel.domain, plugins] # explicit submodule
mcp → [kernel, kernel.domain]
tests / docs → excludedkernel never imports plugins (the load_paths loader is injected, not
imported). kernel.domain is the common contract everyone may depend on.
Explicit submodules (e.g. plugins.builtin.desktop_control) are declared so
tach enforces the boundary transitively (submodules are not auto-inherited).
See CHANGELOG.md for the full release history.
Local run:
python -m pip install -e ".[dev]"
python -m tach check # dependency axis
python -m pytest tests/ # full suiteLicense
Internal / unreleased.
This server cannot be deployed
Maintenance
Related MCP Connectors
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yo…
Model Context Protocol server for the Apideck Unified API. Connect any MCP-compatible agent framework to 100+ accounting systems, HRIS platforms, file storage providers, and more through one integration. More information https://www.apideck.com/mcp-server
Discover and call AI agents via MCP. Supports A2A agents and platform agents with async tasks.
MCP server for secureFlows: token-free URL builders and integration-linting tools for AI agents.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceA Model Context Protocol (MCP) server that supports STDIO, SSE and Streamable HTTP protocols for AI model interactions.5 npm1MIT
- AlicenseNot gradedqualityDmaintenanceEnables MCP clients to connect to LLM/API services using the Model Context Protocol, providing real-time interaction and tool access. Also offers RESTful API endpoints via FastAPI for programmatic integration with existing systems.Apache 2.0
- AlicenseNot gradedqualityDmaintenanceModel Context Protocol server that standardizes tool discovery, execution, and context management for AI applications.MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI agents to discover and execute tools via a secure MCP server with JWT authentication, RBAC, rate limiting, and audit logging.1MIT