MCP Server (Self-Serve)
AgentsMesh ships a built-in MCP server that lets AI agents read and write the canonical .agentsmesh/ directory directly. Agents can list rules, create commands, update permissions, and trigger generate — without leaving the conversation.
Quick start
agentsmesh init seeds .agentsmesh/mcp.json with the server entry automatically, keeping every other key in the file. The seeded entry looks like:
{ "mcpServers": { "agentsmesh": { "type": "stdio", "command": "npx", "args": ["-y", "agentsmesh", "mcp"] } }}After init, run agentsmesh generate to project the entry into each target’s native MCP config file (e.g. .claude/settings.json, .cursor/mcp.json, .gemini/settings.json).
Configuration
Three deployment forms are supported:
| Form | When to use |
|---|---|
npx -y agentsmesh mcp | Zero-install default. Seeded on init. Works on any machine with Node.js. |
command: "agentsmesh" | Recommended after npm install -D agentsmesh. Faster startup; no network round-trip. |
| Global install | Air-gapped or shared machines. npm install -g agentsmesh then use command: "agentsmesh". |
Recommended form (after adding agentsmesh as a dev dependency):
{ "mcpServers": { "agentsmesh": { "type": "stdio", "command": "agentsmesh", "args": ["mcp"] } }}The server reads projectRoot from the process working directory at startup, walking up to the nearest directory with agentsmesh.yaml. The lessons tools also work without agentsmesh.yaml (for example with only the lessons plugin). They use the nearest directory with .agentsmesh/lessons/ (a lessons.json or config.json), even when an agentsmesh.yaml is nearer; else the nearest directory with agentsmesh.yaml; else the git repository root. They never use your home folder. Outside all of these, reads find no lessons, and lessons_add and lessons_deprecate fail with NO_PROJECT. So starting the server in a subdirectory of the project works. No configuration flags are accepted; the MCP host controls the working directory via the cwd field in the MCP server entry when needed.
Tools reference
The server exposes 50 tools grouped by category. All tool errors return a structured envelope { code, message, details? } (see Error codes).
The server runs tool calls one at a time, in the order they arrive. A client can send several calls without waiting for the replies: parallel write calls to the same file (for example three add_mcp_server calls) all keep their changes.
Canonical reads (8)
| Tool | Description |
|---|---|
list_rules | List rules with summary metadata |
get_rule | Get a single rule by name |
list_commands | List commands with summary metadata |
get_command | Get a single command by name |
list_agents | List agents with summary metadata |
get_agent | Get a single agent by name |
list_skills | List skills |
get_skill | Get one skill (frontmatter + body + supporting filenames) |
Skill file read (1)
| Tool | Description |
|---|---|
get_skill_file | Read a skill supporting file by skill name and relative path |
Settings reads (5)
| Tool | Description |
|---|---|
get_config | Read agentsmesh.yaml |
list_mcp_servers | List MCP servers in canonical mcp.json |
get_permissions | Read permissions.yaml |
get_hooks | Read hooks.yaml |
get_ignore | Read ignore patterns |
Capabilities (2)
| Tool | Description |
|---|---|
list_target_capabilities | List the support matrix for all targets |
get_target_capabilities | Get capabilities for a specific target ID |
Canonical mutations (12)
| Tool | Description |
|---|---|
create_rule | Create a new rule |
update_rule | Update a rule (replace or merge) |
delete_rule | Delete a rule |
create_command | Create a new command |
update_command | Update a command |
delete_command | Delete a command |
create_agent | Create a new agent |
update_agent | Update an agent |
delete_agent | Delete an agent |
create_skill | Create a skill with optional supporting files |
update_skill | Update a skill (supportingFiles: string = write, null = delete) |
delete_skill | Delete a skill |
Settings mutations (7)
| Tool | Description |
|---|---|
update_config | Update agentsmesh.yaml (replace or merge) |
add_mcp_server | Add an MCP server entry to .agentsmesh/mcp.json |
update_mcp_server | Update an MCP server entry (replace or merge) |
remove_mcp_server | Remove an MCP server entry |
update_permissions | Update permissions.yaml (replace or append) |
update_hooks | Replace hooks.yaml content |
update_ignore | Update ignore patterns (replace or append) |
Orchestration (6)
| Tool | Description |
|---|---|
generate | Generate target-native config from canonical (lockfileUpdated is true only when the run rewrote .agentsmesh/.lock; a run that changes nothing leaves it alone) |
lint | Lint canonical files |
check | Detect canonical-source and generated-output drift against the lock (result includes canonicalDrift/outputDrift, per-path output arrays, outputsChecked, lockConflict for a lock with git conflict markers, and lessonsGraphError when .agentsmesh/lessons/lessons.json cannot be read) |
diff | Preview generation changes |
import | Import another tool’s config into canonical |
convert | Convert directly from one tool to another |
Pack lifecycle (4)
| Tool | Description |
|---|---|
install | Install a community pack from a URL or local path (auto-classifies skill-pack / canonical / tool-native; --target / --as overrides) |
uninstall | Remove one or more installed packs; mid-batch failures isolated in data.failed[] |
installs_list | Read-only inventory of installed packs (NAME / SOURCE / FEATURES / INSTALLED) |
refresh | Re-fetch and re-apply installed packs against their recorded source/ref. Branch pins re-resolve to the current tip; tag pins re-resolve; SHA pins stay put. Per-pack atomic. |
Lessons (5)
| Tool | Description |
|---|---|
lessons_query | Recall primitive — active lessons whose triggers match the supplied file / command / keyword, relevance-ranked and capped |
lessons_add | Capture primitive — atomically add a lesson; requires at least one effective trigger |
lessons_topics | List every topic with its summary |
lessons_show | Render one topic’s lessons or a single lesson by id (read-only diagnosis view) |
lessons_deprecate | Mark a lesson deprecated, or superseded with a replacement id |
The lessons tools mirror the agentsmesh lessons CLI — same predicates, same guardrails — for agents without shell access. A few details:
- Size caps. The graph may come from a cloned repo, so every answer is bounded. Each rule is cut to 2000 characters, and a
lessons_queryorlessons_showanswer carries at most 32,000 characters of rule text.lessons_showreports how many lessons it cut in anomittedfield. Itstopicfield also takes a lesson id, to show that one lesson. - Always-on lessons.
lessons_querywithalways: trueappliessessionandno_dedupto the always-on lessons too, and counts the ones it hid insuppressed. - Unreadable graph. When
lessons.jsoncannot be read,lessons_topics,lessons_show,lessons_addandlessons_deprecatefail withVALIDATION_FAILED, anddetails.codeisMERGE_CONFLICT,CORRUPT_GRAPH,SCHEMA_INVALIDorNEWER_GRAPH_VERSION.lessons_queryreturns no lessons and writes the reason to stderr. lessons_addchecks. Atrigger_filesglob that can never fire is rejected withVALIDATION_FAILED, anddetails.codesays why:TRIGGER_FILE_OUTSIDE_PROJECT(an absolute path outside the project, or../that climbs out),TRIGGER_FILE_IS_PROJECT_ROOT,TRIGGER_FILE_IS_DIRECTORY(usedir/**) orUNSAFE_GLOB_PATTERN. Other globs are stored project-relative (./src/a.tsbecomessrc/a.ts). A topic id that is not kebab-case isINVALID_TOPIC_ID, andnew_topicwithout a non-blanktopic_summaryisTOPIC_SUMMARY_REQUIRED, bothVALIDATION_FAILED. The non-blockingwarningsincludeDEAD_GLOB(git history shows the glob’s path was renamed or deleted) andPENDING_GLOB(the path does not exist yet; the trigger is kept). See capture guardrails.
The pack-lifecycle tools always run non-interactively. MCP has no stdin TTY, so the documented --force defaults are accepted for every interactive prompt the CLI would surface (bulk select → accept all, broken-link → leave-with-warnings, modified-files → delete-anyway). For finer-grained selection, drive the CLI directly. Input shapes mirror the CLI flags one-for-one (refresh accepts names?: string[], dry_run?, global?); output envelopes match InstallData / UninstallData / InstallsListData / RefreshData documented under install, uninstall, installs, and refresh.
The canonical mutation tools and orchestration tools accept an optional dry_run: true parameter that returns the planned changes without writing to disk. install and uninstall also honor dry_run (the legacy-manifest migration runs in memory only). The lessons_add and lessons_deprecate tools are the exception — they mutate the lessons graph directly and do not accept dry_run.
MCP server edits preserve untouched server fields and top-level configuration fields. A malformed existing mcp.json is rejected instead of overwritten. Skill creation and updates validate all supporting paths and file sizes before writing any files. Change the primary SKILL.md through frontmatter and body; it cannot be overwritten or deleted through supportingFiles.
Resources reference
The server exposes 17 readable resources, derived from the tools that have a resourceUri:
| URI | Mapped tool |
|---|---|
agentsmesh://canonical/rules | list_rules |
agentsmesh://canonical/rules/{name} | get_rule |
agentsmesh://canonical/commands | list_commands |
agentsmesh://canonical/commands/{name} | get_command |
agentsmesh://canonical/agents | list_agents |
agentsmesh://canonical/agents/{name} | get_agent |
agentsmesh://canonical/skills | list_skills |
agentsmesh://canonical/skills/{name} | get_skill |
agentsmesh://canonical/skills/{name}/files/{path} | get_skill_file |
agentsmesh://config | get_config |
agentsmesh://canonical/mcp | list_mcp_servers |
agentsmesh://canonical/permissions | get_permissions |
agentsmesh://canonical/hooks | get_hooks |
agentsmesh://canonical/ignore | get_ignore |
agentsmesh://capabilities | list_target_capabilities |
agentsmesh://capabilities/{targetId} | get_target_capabilities |
agentsmesh://installs | installs_list |
Error codes
All tool errors return a structured envelope { code, message, details? }.
| Code | Meaning |
|---|---|
NOT_FOUND | The requested item does not exist |
ALREADY_EXISTS | A create was attempted for a name that already exists |
VALIDATION_FAILED | Input did not pass schema validation. Also a lessons write the graph validator refused (nothing is written; details.code and details.codes hold the finding codes), and a lessons graph that cannot be read (details.code is MERGE_CONFLICT, CORRUPT_GRAPH, SCHEMA_INVALID or NEWER_GRAPH_VERSION) |
INVALID_NAME | Name contains disallowed characters or is reserved |
PATH_TRAVERSAL | A path argument attempted to escape the canonical directory |
PROTECTED_FILE | The target file (_root.md) cannot be deleted |
LOCK_HELD | The generate lock is held by another process |
NO_PROJECT | No agentsmesh.yaml was found in the working directory. For lessons_add and lessons_deprecate: no lessons project, agentsmesh.yaml or git repository was found |
IO_ERROR | A filesystem read or write failed |
LIMIT_EXCEEDED | A content or file-count limit was reached |
REFRESH_RESOLVE_FAILED | A refresh could not resolve a pack’s source |
REFRESH_APPLY_FAILED | A refresh resolved the source but failed to apply the update |
Security
The MCP server relies on the host trust boundary — no authentication is built in. The host process (Claude Code, Cursor, etc.) controls which servers agents may invoke.
Guards in place:
- Path-traversal protection — all paths are resolved relative to
.agentsmesh/and rejected if they escape it. _root.mdprotection — the root rule cannot be deleted.- Resource limits — individual file writes are capped at 1 MiB; canonical name length, hooks-per-event, args, and env values all have explicit caps.
- Flat canonical names —
create_rule/create_command/create_agentreject names containing/,.., or characters outside[A-Za-z0-9_-]. Names that are Windows reserved devices (CON,AUX,NUL,COM1-9,LPT1-9) or contain<>:|?*are rejected so generation stays portable. - Strict write-tool input validation — every mutation tool is gated by a Zod schema that rejects shell-meta payloads before they reach disk:
add_mcp_server/update_mcp_serverrejectcommandstrings containing any of the shell metacharacters; & | $ \< > ! \or newlines, env keys outside[A-Za-z_][A-Za-z0-9_]*, URLs whose protocol is nothttp(s)://`, args arrays longer than 100, and unknown server fields.update_hooksrequires amatcherfree of CR/LF, requires every entry to havecommandorprompt, and caps each event at 100 entries (50 nested).update_permissionsvalidates each entry againstTool/Tool(matcher)and rejects newlines that could escape YAML quoting.
- Redacted error messages —
McpErrorrefuses to construct messages containing absolute paths, and the server fallback path runs rawError.messagestrings through a redactor before returning them to the client.IO_ERRORenvelopes include the underlyingerrnocode indetailsso failures stay diagnosable without leaking layout.
Troubleshooting
Server does not appear in the tool list
The MCP entry was seeded into .agentsmesh/mcp.json but you must run agentsmesh generate to project it into each target’s native settings file. Run generate, then restart your AI tool.
NO_PROJECT error when calling any tool
The server process started in a directory without agentsmesh.yaml. Set the cwd field in the MCP server entry to your project root, or start your AI tool from the project root. The lessons tools need less: lessons_add and lessons_deprecate fail with NO_PROJECT only outside any lessons project, agentsmesh.yaml or git repository, for example in your home folder.
LOCK_HELD on generate
Another process (e.g. agentsmesh watch or a parallel generate) holds the generate lock. Wait for it to finish or check for stale lock files in .agentsmesh/.
npx form is slow to start
npx -y agentsmesh mcp downloads the package on first use and caches it. For faster startup, install agentsmesh as a dev dependency and switch the entry to command: "agentsmesh", args: ["mcp"].
PATH_TRAVERSAL error
A skill or file path argument contained .. or an absolute path. Use only relative paths within the skill directory.
Migrating existing projects
If your project already has .agentsmesh/mcp.json and you want to add the self-serve server entry manually:
{ "mcpServers": { "agentsmesh": { "type": "stdio", "command": "npx", "args": ["-y", "agentsmesh", "mcp"] } }}Then run agentsmesh generate to project the entry.
Alternatively, re-running agentsmesh init on an existing project will inject the entry if it is absent, without overwriting other canonical files.