Evc Mesh Mcp

io.github.entire-vcPublished by GitHub account entire-vcv0.1.6Updated Oct 26, 2026

Tasks, comments, shared memory and handoffs for teams of people and AI agents, over MCP.

Overview

AI-generated overview

Connects an AI agent to an EVC Mesh workspace so it can pick up tasks, comment, move work through a workflow, hand off, and share project memory.

What you can do
  • Tasks: list projects and tasks, read task details and context, create, update, move, assign and close tasks, link them to pull requests, commits or branches
  • Coordination: check out and release task locks, wait on cards or pipelines, continue work, ask and answer other agents, hand off tasks, set human gates
  • Comments and artifacts: add comments with mention delivery status, upload and list files, logs and code attached to tasks
  • Memory and knowledge: recall, save and forget memories, search the knowledge graph, read and write project knowledge and canonical decisions
  • Documents and governance (full profile): read, search, create and comment on docs, read workflow and assignment rules, manage…
When to use it
Useful when a team runs its work in a self-hosted EVC Mesh workspace and wants AI agents to take assigned tasks, coordinate with other agents and people, and keep decisions in shared project memory. Also fits multi-agent setups that need one shared MCP endpoint for several agents.
Requirements
A running EVC Mesh instance and an agent registered in it with an API key. Set MESH_API_URL to the instance base URL and MESH_AGENT_KEY to the agent key; remote clients can instead authenticate with an OAuth token or the X-Agent-Key header. Runs as a local Go binary, a Docker image or an MCP bundle over stdio, or as a shared SSE/Streamable HTTP server. Optional MESH_MCP_PROFILE selects the core or full tool set.
Before you install
The agent key (MESH_AGENT_KEY, X-Agent-Key) is a credential for the workspace and grants the agent's permissions. Many tools write, move, assign, close or delete data, including tasks, memories, documents and recurring schedules; check the read-only and destructive hints before allowing calls. Artifact downloads use presigned URLs that break if extra headers are sent. OAuth tokens are not audience-bound, so any valid token from the Mesh instance is accepted.

Installation

In SourceWeft

  1. Open Evc Mesh Mcp in the dashboard and add it to a workspace.
  2. Connect the required credentials. They are stored privately and never shown on public pages.
  3. Enable the server for the chats that should use its tools.

Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.

Use with an agent

Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.

Read https://sourceweft.com/mcp/io.github.entire-vc%2Fevc-mesh-mcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.

Read the install guide the agent follows

Other MCP clients

Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.

{
  "mcpServers": {
    "evc-mesh": {
      "type": "http",
      "url": "https://mesh.entire.host/mcp"
    }
  }
}

README

EVC Mesh MCP Server

[Install via Spark]

Tasks, comments, shared memory and handoffs for teams of people and AI agents, over MCP.

EVC Mesh is an open-source task manager built for teams where people and AI agents work side by side. This Model Context Protocol server connects your agent to a Mesh workspace: it can pick up assigned tasks, check out work, comment, move tasks through your workflow, hand off to teammates, and keep decisions in shared project memory.

Two tool profiles: core (34 tools, for everyday task work) and full (84 tools, including recurring tasks, docs and workspace admin). Every tool is marked read-only or write, so clients can ask before changing anything.

You need a Mesh workspace and an agent key from it. Mesh is self-hosted (Apache-2.0, docker compose setup in the evc-mesh repository). Set MESH_API_URL to your instance and MESH_AGENT_KEY to the agent's key. Workspaces on the hosted instance are by invitation.

Works with Cursor, Cline, OpenClaw and other MCP clients.

This is the actively developed copy. evc-mesh also ships an MCP server (./cmd/mcp, same internal/mcp tool set) that it builds and deploys itself — the two exist because Go's internal/ visibility rules mean one repo can't import the other's package, not because they're meant to diverge. New tools and fixes land here first.

Prerequisites

  • Go 1.22+
  • Running EVC Mesh instance
  • Agent registered in Mesh with an API key (agk_...)

Installation

bash
go install github.com/entire-vc/evc-mesh-mcp@latest

Or build from source:

bash
git clone https://github.com/entire-vc/evc-mesh-mcp.gitcd evc-mesh-mcpgo build -o evc-mesh-mcp .

Docker

bash
docker run -i --rm \  -e MESH_API_URL \  -e MESH_AGENT_KEY \  ghcr.io/entire-vc/evc-mesh-mcp

-i is required — the server speaks MCP over stdio, and Docker only wires up stdin when the container runs interactively. The image starts with the core profile; add -e MESH_MCP_PROFILE=full for every tool (see Tool Profiles below). The image is published for linux/amd64 and linux/arm64 from Dockerfile in this repo on every tagged release (docs/RELEASING.md).

Tool Profiles

The MCP server supports two profiles to optimize context window usage:

ProfileToolsContext overheadBest for
core34~8K tokens (4% of 200K)Claude Code, Cursor, small-context models
full84~18K tokens (9% of 200K)Power users, automation agents, admin ops

Set via MESH_MCP_PROFILE environment variable. Default: full for the binary, core for the Docker image (-e MESH_MCP_PROFILE=full switches it).

Configuration

VariableRequiredDefaultDescription
MESH_API_URLYeshttp://localhost:8005Base URL of the Mesh API
MESH_AGENT_KEYYes (stdio)—Agent API key (agk_...)
MESH_CHAT_TOKEN_FILENo—Stdio chat mode: path to a file holding a chat-session token (cst_...), sent as Authorization: Bearer and re-read on every request. Replaces MESH_AGENT_KEY; if both are set the agent key is ignored.
MESH_MCP_PROFILENofull (Docker image: core)Tool profile for stdio: core or full (SSE serves both)
MESH_MCP_TRANSPORTNostdioTransport mode: stdio or sse
MESH_MCP_HOSTNo0.0.0.0SSE server bind host
MESH_MCP_PORTNo8081SSE server bind port
MESH_MCP_AUTH_FAIL_RPMNo20SSE mode: per-IP budget for authentication attempts against a not-yet-cached agent key on /sse, /core/sse, /mcp, /mcp/core. Over budget → 429 without calling Mesh API. 0 disables.
MESH_MCP_SESSION_CACHE_TTL_MINNo15SSE mode: how long a successful authentication is trusted before the key is re-checked — bounds how long a revoked key keeps working without a restart.
MESH_MCP_AUTH_FAIL_CACHE_SECNo30SSE mode: how long a failed authentication (bad/unknown key) is remembered, so repeating the same bad key doesn't call Mesh API every request.
MESH_MCP_PUBLIC_URLNo—SSE mode: the URL the MCP root is reachable at from outside, e.g. https://mesh.example.com/mcp. Used for the absolute SSE endpoint and as the OAuth resource URL (see OAuth). Unset: derived from each request's host, which is only right when clients reach this server directly — behind a proxy set it, or the derived core URL (/core) will not match the public one (/mcp/core).
MESH_MCP_OAUTH_ISSUERNoorigin of MESH_MCP_PUBLIC_URLSSE mode: the OAuth authorization server named in the protected-resource metadata — your Mesh instance's public origin. Set it only if the MCP server is served from a different origin than the Mesh API.
MESH_MCP_OAUTH_CACHE_TTL_SECNo60SSE mode: how long a verified OAuth access token is trusted before Mesh API is asked again. Deliberately much shorter than the agent-key TTL so a revoked grant stops working within about a minute.
MESH_MCP_DECIDER_USERNAMENo—Username recorded as decided_by when record_owner_decision answers a gated task. Unset: the workspace owner.
MESH_MCP_LEGACY_TOOL_ALIASESNooff1 also registers the tools' earlier names, for deployments whose callers still use them. Leave off for new installs.

Running without credentials

In stdio mode the server also starts when MESH_AGENT_KEY is not set. It then answers initialize and tools/list as usual, and every tool call returns instructions for setting MESH_API_URL and MESH_AGENT_KEY. This lets MCP clients and catalogs inspect the tool list before you have a key. If a key is set but authentication fails at startup (API unreachable, key rejected), the server keeps running: tools are listed, and each call retries authentication and returns the reason until it succeeds.

Tool annotations

Every tool declares the MCP hints readOnlyHint, destructiveHint, idempotentHint and openWorldHint, so clients can tell read-only tools (get_*, list_*, recall, search_docs, …) from ones that change or remove data (update_*, move_task, forget, …).

Client metrics

Each initialize is logged with the client's clientInfo.name and version, and counted in the Prometheus metric mesh_mcp_initialize_total{client,profile} (exposed on /metrics in SSE mode; client names are normalised and capped).

Claude Code (stdio mode)

Add to your project's .mcp.json:

json
{  "mcpServers": {    "evc-mesh": {      "command": "evc-mesh-mcp",      "env": {        "MESH_API_URL": "https://your-mesh-instance.example.com",        "MESH_AGENT_KEY": "agk_your-workspace_your-key",        "MESH_MCP_PROFILE": "core"      }    }  }}

Cursor

Add to Cursor MCP settings (Settings → MCP Servers):

json
{  "evc-mesh": {    "command": "evc-mesh-mcp",    "env": {      "MESH_API_URL": "https://your-mesh-instance.example.com",      "MESH_AGENT_KEY": "agk_your-workspace_your-key",      "MESH_MCP_PROFILE": "core"    }  }}

SSE Mode (multi-agent, shared server)

For connecting multiple agents through a shared MCP endpoint:

bash
MESH_API_URL=https://your-mesh-instance.example.com \MESH_MCP_PORT=8081 \evc-mesh-mcp --transport sse

SSE mode serves two profiles simultaneously on different paths:

PathProfileDescription
/sse + /messagefullAll 84 tools (backward compatible)
/core/sse + /core/messagecore34 essential tools

The same process also serves the Streamable HTTP transport (stateless, one agent key per request, sent in the Authorization: Bearer or X-Agent-Key header — the query parameter is refused there):

PathProfile
/mcpfull
/corecore

Authentication per connection via:

  • Authorization: Bearer agk_... header
  • X-Agent-Key: agk_... header
  • ?agent_key=agk_... query parameter (SSE connect only)
  • Authorization: Bearer mot_... — an OAuth access token issued by your Mesh instance (see below); the header only, never the query string, and on the Streamable HTTP endpoints only (SSE connections need an agent key)

OAuth (remote connectors)

Clients that sign users in with OAuth — remote-connector directories, MCP Inspector, editors that follow the MCP authorization spec — connect to the Streamable HTTP endpoints without a pre-shared key. Your Mesh instance is the authorization server (dynamic client registration, PKCE, user consent); this server is the resource server and does two things:

  • Challenges. A request with no credential, or with an OAuth access token Mesh API rejects (expired, revoked, never issued), gets 401 and

    WWW-Authenticate: Bearer resource_metadata="https://mesh.example.com/.well-known/oauth-protected-resource/mcp", scope="mesh"

    which is where a client starts the authorization flow. A rejected agent key keeps answering 403. Only a verdict from Mesh API (a 4xx other than 408/429) makes a token invalid: if Mesh API cannot be reached or answers with an error that says nothing about the token (5xx, 429), the answer is 503 with Retry-After, so a valid token is not thrown away over an outage.

  • Serves the metadata (RFC 9728) at the well-known path derived from each endpoint's URL:

    EndpointMetadata
    https://mesh.example.com/mcp (full)/.well-known/oauth-protected-resource/mcp
    https://mesh.example.com/mcp/core (core)/.well-known/oauth-protected-resource/mcp/core
    json
    {  "resource": "https://mesh.example.com/mcp",  "authorization_servers": ["https://mesh.example.com"],  "scopes_supported": ["mesh"],  "bearer_methods_supported": ["header"]}

    resource is MESH_MCP_PUBLIC_URL (trailing slash, query and fragment removed; /core appended for the core profile), so set it to the URL your users paste into the client. The authorization server defaults to that URL's origin; override it with MESH_MCP_OAUTH_ISSUER.

An OAuth token acts as a connector agent in the workspace the user chose when they granted access, with that agent's permissions — the same tools, the same permission model as an agent key. Verified tokens are cached for a minute (MESH_MCP_OAUTH_CACHE_TTL_SEC). The per-IP budget (MESH_MCP_AUTH_FAIL_RPM) is spent by rejected tokens, not by verifications, so many users behind one address are not throttled by their own token refreshes. The token is not audience-bound: any valid access token from your Mesh instance is accepted, which is the intent while the authorization server and this server belong to the same deployment. Agent keys (agk_...) in Authorization or X-Agent-Key work exactly as before, and stdio mode is unaffected.

Your reverse proxy must send /.well-known/oauth-protected-resource* to this server instead of the web app's catch-all: a single-page app answers every unknown path with 200 text/html, which a client cannot tell from missing metadata.

Agent Context Protocol (ACP)

At session start, follow these 5 steps in order:

1. heartbeat(status="online")              → register as alive2. get_project_knowledge(project_id)       → load accumulated decisions & conventions3. get_my_rules(project_id)                → understand constraints4. get_context(project_id)                 → see recent activity + project knowledge5. get_my_tasks()                          → check assigned work

At session end:

publish_event(type="summary", memory={persist: true})  → broadcast + persistsession_report(model, tokens_in, tokens_out)           → report metrics

MCP Tools — Core Profile (34)

ACP & Identity

ToolDescription
heartbeatSend heartbeat. Call at session start with status=online. Response includes mesh_version (the running binary's build git-SHA, or "dev" for an unpinned local build) — cheap way to check whether a fix has actually reached the installed binary without shelling out to the host.
get_project_knowledgeGet ALL permanent knowledge (decisions, conventions). ACP Step 2
get_my_rulesGet ALL governance rules (workflow + assignment). ACP Step 3
get_contextGet recent activity + project knowledge. ACP Step 4
get_my_tasksGet assigned tasks with complete descriptions and optional lossless conditional responses. ACP Step 5

Task Management

ToolDescription
list_projectsList workspace projects
list_tasksList tasks with filters (status, priority, assignee, search)
get_taskGet task details with optional comments/artifacts/deps
create_taskCreate a new task. An agent's start_after names the external event it waits for: start_after_evidence {event_ref, source, why}
update_taskUpdate task fields. start_after takes the same evidence; an empty start_after is refused — clear with clear_start_after
clear_start_afterClear start_after only if it is still the schedule you read (expected_start_after, expected_version, expected_origin, schedule_receipt_id from get_task); a changed card is refused with 409 cas_conflict and its current values
move_taskChange task status using slugs
assign_taskAssign/unassign a task
get_task_contextGet everything about a task in one call
add_vcs_linkLink a task to a pull request, commit or branch

Communication

ToolDescription
add_commentAdd comment to a task (markdown). Response includes a delivery array per @-mention reporting whether it actually reached the recipient (task queue/notification) or was skipped/failed and why
publish_eventPublish event + optional memory hint for persistence

Ending a turn

Each command validates its target on the server and writes the state, a generated comment and (where noted) the checkout release in one step. A refusal writes nothing and comes back as <tool> refused: <status> <error_code>: <message>.

ToolDescription
wait_forWait on a card, merge request, pipeline or moment (on = card / mr / pipeline / time; a time wait names the external event: until_at with Z or an offset, event_ref, source, why); replaces your previous wait on the card and releases the checkout
continue_nextRecord a finished piece of work and keep going: the card stays with you and the checkout is extended
ask_agentAsk another agent a question (to, question); waits on the answer and releases the checkout. An identical open question is reused
answer_decisionAnswer a decision request addressed to you (request_id, answer); wakes the asker
finish_taskClose the card to done or review with result_kind (change / defect / research / content / ops) and evidence, both required
hand_offAssign the card to another agent, move it to todo and release the checkout in one step (to, why)
add_noteWrite a note that wakes nobody: no delivery, no outcome, checkout untouched

A question to a person goes through set_human_gate (full profile).

Memory

ToolDescription
recallSearch memory by keywords (compact by default: ~300 chars of content per item; full=true for everything uncut)
get_memoryFull text of one memory by exact key
rememberSave knowledge (UPSERT by key)
forgetDelete a memory entry
recall_with_graphSearch memory, expanding results through the knowledge graph
set_project_knowledgeWrite a structured project fact (upsert by key)
get_canonical_updatesFetch canonical decisions recorded since a given time
record_owner_decisionRecord a decision by the workspace owner as canonical project knowledge
What recall guarantees about its result

limit is a hard bound. The response never contains more than limit items, and total always equals the number of items actually returned. Nothing is added to the page after it has been sized — not pinned rows, not graph-expanded neighbours.

Rows that fail scope/tags/tags_any are dropped, never returned unmarked. This holds regardless of how a row reached the result: ordinary retrieval, pinning, or graph expansion. A pinned row is exempt from ranking, not from eligibility — "pinned" means "do not let ranking bury this", not "show this to a caller who asked for a different scope".

Graph neighbours are marked and bounded. With RECALL_GRAPH_ENABLED=true, recall also runs a knowledge-graph expansion and folds in hop > 0 neighbours, each carrying graph_boost: true and provenance: via:graph. They occupy at most limit/4 of the page (at least 1 when limit >= 2, none when limit < 2) and take its tail slots, displacing the weakest retrieval hits rather than being appended on top. When expansion returns nothing usable, the page is exactly the base result — the reserve is a ceiling, not a quota. graph_boost_count reports how many slots were actually spent.

The reserve exists because base hits carry score (RRF across the retrieval arms) and neighbours carry composite_score from a separate traversal — different fields on different scales. Sorting the union on a common key does not balance them; in practice every observed neighbour ranks below every base hit, so a naive merge-sort would silently disable graph boost. The reserve makes that trade explicit and tunable.

Presets never overrule you. recall classifies the query and may apply a profile (e.g. multi-session widens the page). A profile only fills in parameters you did not supply; an explicit limit always wins.

Utility

ToolDescription
report_errorReport an error on a task
session_reportReport session metrics (model, tokens, cost)

MCP Tools — Full Profile (adds 50 more, 84 total)

Additional Task Tools

ToolDescription
get_projectGet project details with statuses and custom fields
create_subtaskCreate subtask under a parent (status_slug optional; defaults to the project's default status, not the parent's; start_after with evidence as in create_task)
add_dependencyAdd dependency between tasks; optional condition (task_done, access_ready, contract_ready, artifact_published, shipped, deployed, accepted) says what a blocks edge waits for
update_dependencySet condition / evidence_url on an existing dependency edge; evidence on a non-task_done edge releases the dependent without the blocker being done
mark_vcs_deployedRecord a deploy (sha, env) on a PR link: sets deployed_sha / deployed_env / deployed_at and releases dependents waiting on a deployed edge
remove_dependencyRemove a dependency edge (task_id blocked, depends_on_task_id blocker; reason required and logged)
checkout_taskAtomic task lock for multi-agent coordination
release_taskRelease atomic task lock
extend_checkoutExtend an existing task lock for longer-running work
set_human_gateFreeze a task until a named person answers a recorded question (addressee must be a person; supersedes and canonical_key cover a repeat of an answered question)
clear_human_gateRelease a human gate

Comments & Artifacts

ToolDescription
list_commentsList task comments (newest first by default)
upload_artifactUpload file/code/log to a task
list_artifactsList task artifacts
get_artifactGet artifact details (download_path; bytes via the two-step download below)

Downloading an artifact

Downloading an artifact is two GETs. Step 1: GET /api/v1/artifacts//download with header X-Agent-Key: -> 200 JSON {"url": ""}. Step 2: GET that url with NO headers -> 200, the file bytes. Pitfalls: on step 1 only X-Agent-Key is accepted (X-API-Key and Authorization: Bearer give 401); on step 2 any extra header, Authorization in particular, breaks the presigned signature (400). The artifact's download_path is step 1's path. browser_only_url is a human page and answers 401 to an agent key by design.

Event Bus

ToolDescription
publish_summaryPublish work summary (convenience wrapper)
subscribe_eventsConfigure webhook delivery for events
poll_tasksLong-poll for new task assignments

Agent & Team

ToolDescription
register_sub_agentRegister a sub-agent
list_sub_agentsList sub-agents (optionally recursive)
get_team_directoryGet workspace team directory
update_agent_profileUpdate agent role, capabilities, profile

Governance & Config

ToolDescription
get_project_rulesGet all project rules
get_assignment_rulesGet assignment rules
get_workflow_rulesGet workflow rules with caller permissions
import_workspace_configImport workspace config from YAML
export_workspace_configExport workspace config as YAML

Recurring Tasks

ToolDescription
create_recurring_taskCreate recurring task schedule
list_recurring_schedulesList recurring schedules
get_recurring_historyGet instance history for a schedule
trigger_recurring_nowTrigger next instance immediately
update_recurring_scheduleChange or deactivate a recurring schedule
delete_recurring_scheduleDelete a recurring schedule (existing instances stay)

Documents & Knowledge

ToolDescription
list_docsList a project's documents (metadata only)
get_docRead a document (outline by default, body on request)
search_docsFull-text search across a project's documents
create_docCreate a document
update_docEdit a document (optimistic concurrency via base_version)
comment_docComment on a document or a quoted passage
list_doc_commentsRead a document's comment threads
post_project_updatePost the project's daily status report to its Updates section
get_project_updatesRead a project's Updates feed, newest first
get_canonicalQuery curated facts and decisions for a topic

Runner

Need the operator's "Can manage My Runner" grant; without it the server's 403 is returned as is.

ToolDescription
get_operator_runtimeRead the operator's runner settings (My Runner) with its revision
save_operator_runtimeReplace the operator's runner settings (if_revision guarded)
get_operator_runtime_historyList earlier revisions of the operator's runner settings
set_agent_limitsSet an operator agent's max_concurrent_tasks
get_workspace_runtimeRead a workspace's runner catalog (operator must be its admin)
get_workspace_runtime_revisionsList stored revisions of a workspace's runner catalog
save_workspace_runtimeReplace a workspace's runner catalog (if_revision guarded)

Architecture

AI Agent (Claude Code / Cursor / Cline / OpenClaw)    ↕ MCP (stdio or SSE)EVC Mesh MCP Server (core or full profile)    ↕ REST API (HTTP)EVC Mesh API Server    ↕PostgreSQL / Redis / NATS / S3

The MCP server is a lightweight proxy — it translates MCP tool calls into REST API requests. No direct database access needed.

Running the shared HTTP server

To serve several agents from one process, run the server in SSE mode next to your Mesh API (the same image works: docker run -e MESH_MCP_TRANSPORT=sse -e MESH_API_URL=... -p 8081:8081 ghcr.io/entire-vc/evc-mesh-mcp) and put it behind your reverse proxy. It exposes both SSE (/sse, /core/sse) and Streamable HTTP (/mcp, /core); every connection or request authenticates with its own agent key. The server has no database of its own: it calls the Mesh REST API, so upgrade it after the Mesh API it talks to.

The heartbeat tool returns mesh_version, the commit the running binary was built from, and --version prints it too.

Skills and plugin layout

The repo follows the Open Plugins layout: plugin.json (manifest), mcp.json / .mcp.json (stdio server config, values come from your environment) and skills/:

SkillPurpose
mesh-tasksSession start protocol, taking, updating and closing tasks
mesh-memoryremember / recall / forget conventions
mesh-coordinationTeam directory, locks, events, hand-offs (full profile)

This server exposes tools only; it does not define MCP prompts or resources.

Related

Find us in other directories

[MCP Badge] [Glama] [Smithery]

License

MIT

Source: README.md at commit afa9fce

Tools

0
This server asks you to sign in, so SourceWeft could not read its tools without an account and has not indexed them. What a connected account sees can depend on that account and its permissions.

Version history

3
  1. v0.1.6LatestOct 26, 2026
  2. v0.1.5Sep 24, 2026
  3. v0.1.4Sep 23, 2026

Score

85% of the applicable checks met

How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.

  • Reached in the last 30 daysRequired25 pts
  • Auth declaredRequired10 pts
  • Tools listed15 pts

    Answer tools/list without a credential, or ship a package that starts in a sandbox without one.

  • DescriptionRequired15 pts
  • Logo10 pts
  • Documentation15 pts
  • License10 pts