A side-by-side look at the Evc Team Relay MCP and Nouz MCP servers: transport, auth, tools, quality signals, and the config to install either one in Claude, Cursor, Windsurf or VS Code.
Verdict: choose Evc Team Relay MCP for knowledge & memory work as a local process; choose Nouz for knowledge & memory as a local process. You can also run both side by side in one mcpServers block.
RELAY_CP_URL, RELAY_AGENT_KEY, RELAY_EMAIL, RELAY_PASSWORD.authenticate, list_shares, list_files.OBSIDIAN_ROOT, NOUZ_CONFIG, EMBED_API_URL.read_file, write_file, update_metadata.Rows where the two servers differ are marked.
| Spec | ||
|---|---|---|
| Category | Knowledge & Memory | Knowledge & Memory |
| Quality signal | 61/100 · Good | 59/100 · Good |
| Install command | Confirmed | Confirmed |
| Transport | Local subprocess (stdio) | Local subprocess (stdio) |
| Auth | other | Not declared |
| Pricing | Free | Not declared |
| Required env vars | RELAY_CP_URLRELAY_AGENT_KEYRELAY_EMAILRELAY_PASSWORD | OBSIDIAN_ROOTNOUZ_CONFIGEMBED_API_URL |
| Verified owner | Community listing | Community listing |
| GitHub stars | 3 | 22 |
| Directory activity | 4 views 0 installs 0 upvotes | 1 views 0 installs 0 upvotes |
| Tools | 9 | 8 |
| Full listing | View Evc Team Relay MCP | View Nouz |
authenticateCheck which auth mode is active (agent key or email/password) and log in if needed.
Takes no arguments; call it first, once, before any other tool.
In agent-key mode (RELAY_AGENT_KEY or RELAY_AGENT_KEYS is set): no login
is needed — each request carries X-Agent-Key directly, this just reports
which mode is active.
In email/password mode: logs in with the RELAY_EMAIL and RELAY_PASSWORD
env vars. The resulting token is managed internally; subsequent tool
calls use it automatically — you never need to pass it yourself.
list_sharesList the shared folders and documents this key or account can access.
Only lists what auth mode/key was granted — it does not create or change
access. Example: `list_shares(kind="folder")`.
In multi-key mode (RELAY_AGENT_KEYS set): returns metadata for every share
that has a configured key, fetched via per-share agent-key auth.
RELAY_AGENT_KEYS is typically keyed by share UUID, but the bare
share-metadata endpoint (/v1/web/shares/{ref}) only resolves web slugs —
a UUID always 404s there. When that happens this falls back to the
UUID-addressable files-index endpoint, which proves the share is real
and reachable but can't report kind/path/visibility (reported as
kind="unknown", plus a file_count instead).
A per-share failure (bad key, wrong share, share genuinely gone) is
NEVER silently dropped — it lands in the response's `errors` field.
"Couldn't check this share" and "checked, it doesn't exist" must stay
distinguishable; collapsing both into an empty list is what let a
config/auth problem read as "you have no shares".
In single-key mode (RELAY_AGENT_KEY only): returns an empty list — the
single key is tied to one share but its identity is unknown; call list_files
or tr_search directly with the known share_id.
In email/password mode: returns all shares the user has access to.
Args:
kind: Filter by share type — "doc" or "folder". Empty for all.
owned_only: If true, only return shares owned by the user (email/password mode only).
Returns:
On full success: a bare JSON array of shares (id, kind, path,
visibility, user_role — or id/kind="unknown"/file_count for
UUID-resolved entries).
If any share failed to resolve: a JSON object
{"shares": [...], "errors": {share_ref: "reason"}} instead of a
silently-shortened array.
list_filesList every file in a shared folder with its metadata.
Read-only; does not download file contents (use read_file for that).
In agent-key mode (RELAY_AGENT_KEYS or RELAY_AGENT_KEY is set): uses the
agent-key endpoint; share_id may be a UUID or web slug.
In email/password mode: share_id must be a UUID.
Args:
share_id: UUID or web slug of the folder share, e.g.
"a1b2c3d4-..." or "research-vault".
Returns:
Object with share_id and files map (path -> metadata). The exact set
of metadata keys per file is server-controlled, hence the loose
dict[str, Any] shape rather than a strict per-field schema.
tr_searchFind files in a shared folder by a case-insensitive match on path or name.
Read-only; does not download file contents (use read_file for that).
Example: `tr_search(share_id="research-vault", query="roadmap")`.
In agent-key mode (RELAY_AGENT_KEY is set): share_id may be UUID or web slug.
In email/password mode: share_id must be a UUID.
Args:
share_id: UUID or web slug of the folder share.
query: Search string matched case-insensitively against file paths.
limit: Max results to return (default 20).
Returns:
JSON list of matching files:
[{"id": doc_id_or_null, "title": filename_without_ext, "path": full_path,
"relay_url": "relay://<slug>/<path>", "updated_at": null}]
read_fileRead one file from a shared folder by its path.
Read-only. Returns the full file content in one response — there is no
partial/range read.
In agent-key mode (RELAY_AGENT_KEY is set): fetches via the agent-key
download endpoint; share_id may be a UUID or web slug.
In email/password mode: fetches via the same CAS download endpoint used by
agent-key mode, over Bearer JWT instead of X-Agent-Key; share_id must be a UUID.
Args:
share_id: UUID or web slug of the folder share.
file_path: File path within the folder (e.g. "Marketing/plan.md").
Returns:
{"path", "content", "format"} on success, or {"error": ...} if the
file doesn't exist — two distinct shapes on the same 200-equivalent
outcome, hence dict[str, Any] rather than a strict per-field schema
(a stricter schema would reject the error shape as invalid output).
read_documentReserved for live document content; not yet available on the server, use read_file.
Always raises: the control-plane has no REST route for reading a
document's live content by ID for either DOC-kind shares or a
folder-share file's doc_id (that concept doesn't exist in the current
CAS-based folder sync model). This is a genuine backend gap, not an
agent-key-vs-JWT restriction. Use read_file for folder shares instead —
it works in both agent-key and JWT mode.
Args:
share_id: UUID of the share (for ACL check).
doc_id: Document UUID. Defaults to share_id for doc shares.
key: Yjs shared type key. Default "contents".
upsert_fileCreate or overwrite a file in a shared folder; it syncs into subscribers' vaults. Agent key only.
**Write access is agent-key-only by design** — this is the sanctioned,
permanent policy (not a temporary gap): agent-key mode is the only
authorized write path in this MCP server.
**Agent key mode** (RELAY_AGENT_KEY is set):
- share_id may be the share UUID or web slug (e.g. "research-vault")
- Folder shares use /sync-upload → file enters the CRDT sync store and
appears in subscribers' local Obsidian vaults on the next sync cycle
- Doc shares fall back to /upload (web-publish only)
- list_files, read_file, and tr_search also work with the same agent key
**Email/password (JWT) mode** — always raises; intentionally read-only.
There is no write route reachable by JWT for an arbitrary (non-web-
published) folder share, and even if one existed, JWT mode stays
read-only by policy. Use agent-key mode for writes.
Args:
share_id: Share UUID (email/password mode) or web slug (agent key mode).
file_path: File path within the share (e.g. "notes/todo.md").
content: Full text content to write.
Returns:
Object with path, size/operation, and optional public_url (agent-key
mode). The exact set of keys is server-controlled (plus the
"operation" key added here), hence dict[str, Any].
write_documentReserved for live document writes; not yet available on the server, use upsert_file.
Always raises: the control-plane has no REST route for writing a
document's live content by ID (doc-share content is CRDT/WebSocket-only).
This is a genuine backend gap in BOTH agent-key and JWT mode, not an
agent-key-vs-JWT restriction — but were a route ever added, per the
sanctioned write policy (agent-key writes only) JWT mode would still be
read-only.
Args:
share_id: UUID of the share (for ACL check).
doc_id: Document UUID.
content: Full text content to write (replaces entire document).
key: Yjs shared type key. Default "contents".
delete_fileReserved for per-file deletion; not yet available on the server.
Always raises: the control-plane has no DELETE route for an individual
folder-share file in ANY auth mode (agent-key or JWT) — this isn't a
JWT-vs-agent-key gap, per-file deletion simply isn't implemented
server-side yet. Note this is independent of the agent-key-only write
policy that governs upsert_file: even once/if a delete route lands, it
would follow that same policy (agent-key-only, JWT read-only).
Args:
share_id: UUID of the folder share.
file_path: File path within the folder (e.g. "old-note.md").
read_fileRead one Markdown note from the local knowledge base. Returns the note body, YAML frontmatter, hierarchy metadata, parent links, explicit tags, and warnings as JSON. Use this before write_file when you need to preserve existing content or inspect current metadata. Side effect: refreshes this file in the local SQLite index so later classification and parent suggestions use current data. It never changes the file.write_fileCreate or replace one Markdown note with YAML metadata. Use it when an agent has an explicit final content body and metadata to save. This is a destructive write: it replaces the complete file, unless content_lock=true is used to preserve the existing body and update only metadata. Before writing, the server validates that parent links do not create graph cycles, syncs parents and parents_meta, and then refreshes the local index. Use read_file first for existing notes and suggest_metadata first when you want classification hints.update_metadataUpdate only YAML frontmatter for an existing note and preserve the Markdown body exactly. Use this for safe changes to type, level, sign, artifact_sign, tags, parents, and parents_meta when the note content must not be touched.list_filesList notes already known to the local index. Returns lightweight records with path, type, level, and sign, without loading full note bodies. Use this for inventory, filtering, and finding files to inspect next. Set no_metadata=true to find Markdown files without YAML metadata. Use get_children or get_parents when you need graph traversal from a specific note.get_childrenTraverse the hierarchy downward from one note. Returns all direct and transitive child note paths from the local graph index. Use this to answer 'what does this topic/module contain?' It is read-only and does not recompute semantic classification. Use get_parents for the opposite direction.get_parentsReturn the parent links of one note from the graph index. Each result includes the parent entity name and link_type, such as hierarchy, derived_from, semantic, temporary, tag, analogy, or error. Use this to understand where a note belongs before editing links. It is read-only. Use suggest_parents when a note has no parents and you want candidate links.suggest_metadataAnalyze one note and propose knowledge-graph metadata for review. Returns suggested domain sign, material type, hierarchy level, explicit tags, tag quality, tag candidates with chunk evidence, bridge candidates, and hierarchy warnings. Use this before write_file when you want classification help, or to audit an existing note. It is read-only and never edits YAML. Semantic fields require embeddings and are available in PRIZMA/SLOI modes. The optional context object lets an agent test metadata overrides without changing the note.index_allScan the whole Markdown vault and rebuild the local SQLite index of files, metadata, and graph links. Use this after adding, moving, or reorganizing notes outside NOUZ. It is safe to run repeatedly and reports missing parent links. In PRIZMA/SLOI, with_embeddings=true also updates file and chunk embeddings for retrieval and semantic classification, which is slower and requires an embedding provider. This tool indexes data; it is not a search tool.Paste either block (or both) into your client config, e.g. claude_desktop_config.json or ~/.cursor/mcp.json. We only show a config when the install command is confirmed.
{
"mcpServers": {
"evc-team-relay-mcp": {
"command": "uvx",
"args": [
"evc-team-relay-mcp"
],
"env": {
"RELAY_CP_URL": "YOUR_RELAY_CP_URL_HERE",
"RELAY_AGENT_KEY": "YOUR_RELAY_AGENT_KEY_HERE",
"RELAY_EMAIL": "YOUR_RELAY_EMAIL_HERE",
"RELAY_PASSWORD": "YOUR_RELAY_PASSWORD_HERE"
}
}
}
}
{
"mcpServers": {
"nouz": {
"command": "uvx",
"args": [
"nouz-mcp"
],
"env": {
"OBSIDIAN_ROOT": "YOUR_OBSIDIAN_ROOT_HERE",
"NOUZ_CONFIG": "YOUR_NOUZ_CONFIG_HERE",
"EMBED_API_URL": "YOUR_EMBED_API_URL_HERE"
}
}
}
}