Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -359,13 +359,13 @@ Browser-native hive-mind for CLI coding agents - Claude Code, Codex, Gemini, and
</td>
<td width="50%" valign="top">

[![banner-gif](https://github.com/user-attachments/assets/867d9329-ce9a-496f-ab1e-15c77974e5fa)](https://github.com/tt-a1i/evermemos-mcp)
[![banner-gif](https://github.com/user-attachments/assets/8e217d39-5d15-4c6c-9b54-3e83add4e0f2)](https://github.com/EverMind-AI/EverOS-MCP)

#### AI Coding Assistants With EverOS
#### MCP Server for AI Coding Assistants

Universal long-term memory layer for AI coding assistants, powered by EverOS.
Plug EverOS memory into Claude Code, Codex, Claude Desktop or Cursor with `uvx everos-mcp`. Works with EverOS Cloud and with this self-hosted server.

[Code](https://github.com/tt-a1i/evermemos-mcp)
[Code](https://github.com/EverMind-AI/EverOS-MCP) · [Setup guide](docs/mcp.md)

</td>
</tr>
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ already know what you want to do and need to know exactly how.
| [knowledge.md](knowledge.md) | Knowledge base module — upload, search, taxonomy, storage layout |
| [reflection.md](reflection.md) | Reflection — offline memory consolidation: enable, schedule, storage, triggering |
| [cli.md](cli.md) | `everos` CLI subcommands + env var conventions |
| [mcp.md](mcp.md) | Connect MCP clients (Claude Code, Codex, Cursor, Claude Desktop) through the official `everos-mcp` server |
| [storage_layout.md](storage_layout.md) | Memory-root tree + frontmatter chassis + EntryId encoding |
| [prompt_slots.md](prompt_slots.md) | PromptSlot loader — bundled default prompts (Layer 1 live; app/runtime overlays planned) |
| [configuration.md](configuration.md) | TOML / env-var configuration reference |
Expand Down
84 changes: 84 additions & 0 deletions docs/mcp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Connect MCP clients

EverOS exposes its memory to MCP (Model Context Protocol) clients — Claude Code, Codex,
Claude Desktop, Cursor and any other MCP host — through the official **everos-mcp**
server: [PyPI `everos-mcp`](https://pypi.org/project/everos-mcp/) ·
[source](https://github.com/EverMind-AI/EverOS-MCP).

`everos-mcp` is a separate process that runs next to your EverOS server. It speaks MCP to
the host over stdio and calls this server's `/api/v2/memory/*` endpoints. It does not start
or stop EverOS for you.

- [Prerequisites](#prerequisites)
- [Add the server to your client](#add-the-server-to-your-client)
- [What the assistant gets](#what-the-assistant-gets)
- [Behaviour on a self-hosted server](#behaviour-on-a-self-hosted-server)
- [Remote hosts](#remote-hosts)

## Prerequisites

1. `everos init` done and the LLM / embedding API keys filled in (`everos.toml`).
2. `everos server start` running — default `http://127.0.0.1:8000`. Start it before the
host launches the MCP server, and keep it running.
3. [`uv`](https://docs.astral.sh/uv/getting-started/installation/) installed; `uvx` runs
`everos-mcp` without a manual install.

No API key is needed when `EVEROS_BASE_URL` points at your own server.

## Add the server to your client

```bash
# Claude Code
claude mcp add everos -e EVEROS_BASE_URL=http://127.0.0.1:8000 -- uvx everos-mcp

# Codex
codex mcp add everos --env EVEROS_BASE_URL=http://127.0.0.1:8000 -- uvx everos-mcp
```

Claude Desktop, Cursor and other JSON-configured clients:

```json
{
"mcpServers": {
"everos": {
"command": "uvx",
"args": ["everos-mcp"],
"env": { "EVEROS_BASE_URL": "http://127.0.0.1:8000" }
}
}
}
```

Optional environment variables: `EVEROS_USER_ID` (memory owner, default `default-user`),
`EVEROS_APP_ID` / `EVEROS_PROJECT_ID` (scope, default `default`). The full list is in the
[everos-mcp README](https://github.com/EverMind-AI/EverOS-MCP#configuration).

## What the assistant gets

Seven tools, backed by this server's `/api/v2/memory/*` endpoints: `get_profile`,
`add_memory`, `search_memory`, `list_memories`, `record_trajectory`,
`recall_agent_experience` and `forget_session` (not yet available here, see below). The
server also ships an autonomy protocol through MCP `instructions`, so capable hosts load the
profile at session start, save new facts and recall context without being asked. The current tool list and the protocol are
documented in the [everos-mcp README](https://github.com/EverMind-AI/EverOS-MCP#tools);
this page only covers what is specific to a self-hosted EverOS.

## Behaviour on a self-hosted server

- **`forget_session` is not available yet.** Self-hosted EverOS has no session-scoped delete
endpoint ([#483](https://github.com/EverMind-AI/EverOS/issues/483)); the tool reports this
instead of failing. Memories are Markdown files under the memory root (`~/.everos/` by
default) — delete them there.
- **New memories become searchable shortly after saving.** `add_memory` returns once
extraction has written the Markdown; the search index catches up a moment later.
`list_memories` shows new entries sooner than `search_memory`.
- **Trajectories only become cases when they pass the quality gate.** Short or
straightforward runs are stored as episodes but produce no reusable case, so
`recall_agent_experience` stays empty until a substantial task has been recorded.

## Remote hosts

To serve MCP over HTTP instead of stdio (hosts on another machine, or OAuth-only hosts),
run `everos-mcp --transport http` on the machine that can reach your EverOS server and put
it behind your gateway. Configuration is described in the
[everos-mcp README](https://github.com/EverMind-AI/EverOS-MCP#configuration).
8 changes: 4 additions & 4 deletions docs/use-cases.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,13 @@ Browser-native hive-mind for CLI coding agents - Claude Code, Codex, Gemini, and
</td>
<td width="50%" valign="top">

[![banner-gif](https://github.com/user-attachments/assets/867d9329-ce9a-496f-ab1e-15c77974e5fa)](https://github.com/tt-a1i/evermemos-mcp)
[![banner-gif](https://github.com/user-attachments/assets/8e217d39-5d15-4c6c-9b54-3e83add4e0f2)](https://github.com/EverMind-AI/EverOS-MCP)

#### AI Coding Assistants with EverOS
#### MCP Server for AI Coding Assistants

Universal long-term memory layer for AI coding assistants, powered by EverOS.
Plug EverOS memory into Claude Code, Codex, Claude Desktop or Cursor with `uvx everos-mcp`. Works with EverOS Cloud and with this self-hosted server.

[Code](https://github.com/tt-a1i/evermemos-mcp)
[Code](https://github.com/EverMind-AI/EverOS-MCP) · [Setup guide](mcp.md)

</td>
</tr>
Expand Down
5 changes: 5 additions & 0 deletions src/everos/entrypoints/cli/commands/init_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
from everos.config.settings import resolve_root
from everos.entrypoints.cli._log_setup import configure_cli_logging

from .server import MCP_GUIDE_URL

_EVEROS_TEMPLATE = Path(__file__).resolve().parents[3] / "config" / "default.toml"
_OME_TEMPLATE = Path(__file__).resolve().parents[3] / "config" / "default_ome.toml"

Expand Down Expand Up @@ -97,3 +99,6 @@ def init(
typer.echo(f" 1. Edit {everos_toml} — fill in API keys (see comments inside)")
root_flag = f" --root {resolved}" if root else ""
typer.echo(f" 2. Run: everos server start{root_flag}")
typer.echo(
f" 3. Connect an MCP client (Claude Code, Codex, Cursor): {MCP_GUIDE_URL}"
)
25 changes: 25 additions & 0 deletions src/everos/entrypoints/cli/commands/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,25 @@
no_args_is_help=True,
)

# The wheel ships only ``src/everos``, so the guide has to be linked, not pathed.
MCP_GUIDE_URL = "https://github.com/EverMind-AI/EverOS/blob/main/docs/mcp.md"

_WILDCARD_BINDS = {"0.0.0.0", "::", ""}


def mcp_base_url(host: str, port: int) -> str:
"""The ``EVEROS_BASE_URL`` a client on this machine should use.

``host`` is the bind address: a wildcard bind (``0.0.0.0`` / ``::``) is
not something a client can connect to, so it becomes loopback; IPv6
literals are bracketed so the result is a valid URL.
"""
if host in _WILDCARD_BINDS:
host = "127.0.0.1"
elif ":" in host and not host.startswith("["):
host = f"[{host}]"
return f"http://{host}:{port}"


@app.command("start")
def start(
Expand Down Expand Up @@ -81,6 +100,12 @@ def start(

bootstrap_logger = logging.getLogger("everos.cli.server")
bootstrap_logger.info("starting everos on %s:%d", host_resolved, port_resolved)
bootstrap_logger.info(
"once up, MCP clients connect with: uvx everos-mcp, "
"EVEROS_BASE_URL=%s (guide: %s)",
mcp_base_url(host_resolved, port_resolved),
MCP_GUIDE_URL,
)
if host_resolved == "0.0.0.0":
bootstrap_logger.warning(
"binding to 0.0.0.0 exposes the API on all interfaces; EverOS "
Expand Down
3 changes: 3 additions & 0 deletions tests/unit/test_entrypoints/test_cli/test_init_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ def test_output_shows_next_steps(runner: CliRunner, tmp_path: Path) -> None:
result = runner.invoke(app, ["init", "--root", str(target)])
assert "Next steps" in result.output
assert "everos server start" in result.output
assert (
"https://github.com/EverMind-AI/EverOS/blob/main/docs/mcp.md" in result.output
)


# ``os`` imported above just to keep ruff from complaining; remove if Ruff
Expand Down
41 changes: 41 additions & 0 deletions tests/unit/test_entrypoints/test_cli/test_server_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,44 @@ def test_start_with_root_option(
result = CliRunner().invoke(root_app, ["server", "start", "--root", str(tmp_path)])
assert result.exit_code == 0, result.stdout
assert "kwargs" in captured


@pytest.mark.parametrize(
("host", "port", "expected"),
[
("127.0.0.1", 8000, "http://127.0.0.1:8000"),
("0.0.0.0", 8000, "http://127.0.0.1:8000"),
("::", 9000, "http://127.0.0.1:9000"),
("::1", 8000, "http://[::1]:8000"),
("10.0.0.5", 8765, "http://10.0.0.5:8765"),
],
)
def test_mcp_base_url_is_something_a_client_can_dial(
host: str, port: int, expected: str
) -> None:
assert server_mod.mcp_base_url(host, port) == expected


def test_start_logs_mcp_hint_with_client_url(captured: dict[str, object]) -> None:
import logging

records: list[str] = []

class _Collect(logging.Handler):
def emit(self, record: logging.LogRecord) -> None:
records.append(record.getMessage())

handler = _Collect()
logger = logging.getLogger("everos.cli.server")
logger.addHandler(handler)
try:
result = CliRunner().invoke(
root_app, ["server", "start", "--host", "0.0.0.0", "--port", "9000"]
)
finally:
logger.removeHandler(handler)
assert result.exit_code == 0, result.stdout
hint = [r for r in records if "uvx everos-mcp" in r]
assert hint, records
assert "EVEROS_BASE_URL=http://127.0.0.1:9000" in hint[0]
assert server_mod.MCP_GUIDE_URL in hint[0]
Loading