MCP server
Setting up the local MCP server
Configure the @myna-sh/mcp server for Claude Code, Cursor, and other MCP clients over stdio or streamable HTTP.
Connecting a chat agent like Claude or ChatGPT? You do not need this page — use the hosted MCP server at
https://api.myna.sh/mcpinstead. This page covers running the server yourself, which is what local coding agents want.
@myna-sh/mcp gives coding agents direct, scoped access to Myna. It is a thin adapter over the management API (it wraps @myna-sh/sdk/management), exposing 62 tools and 6 myna:// resources — see the tool reference for the full list. Fourteen of those belong to Feedback and ten to Analytics; each set is offered only when the project runs that product, because a tool an agent cannot use still costs it context and still makes every other tool harder to choose. All content writes are drafts grouped into change sets; nothing goes live implicitly. Destructive tools — deleting an entry, publishing a change set, restoring a revision — additionally require confirm: true in the call, and publishing requires a credential with the content:publish scope. An agent with a write-only key can draft and preview but cannot ship.
One command
Everything on the rest of this page is JSON to transcribe, and transcription is not a design decision. If you have the CLI, let it write the configuration instead:
$ myna mcp install
✓ claude-code (project): /home/me/site/.mcp.json
✓ cursor (project): /home/me/site/.cursor/mcp.json
Credential written to /home/me/.config/myna/mcp.json (0600).
Restart the client to pick up the new server.
With no arguments it configures every MCP client it detects on this machine, using the project you have linked. Name clients explicitly to be selective — myna mcp install cursor — and see what it knows about with myna mcp list:
$ myna mcp list
CLIENT DETECTED SCOPES MYNA
─────────── ──────── ───────────── ────────
claude-code yes project, user project
cursor yes project, user project
vscode project
windsurf user
codex yes user (manual)
Two things it will not do. It never writes a credential into a client's configuration file — most of those files live in the repository — putting it in ~/.config/myna/mcp.json at 0600 instead, which is where the server already looks (see multiple named projects below). And it never replaces an existing server entry without --force, because a configuration it did not write is one somebody meant.
| Flag | Effect |
|---|---|
--transport http |
Configure the hosted server over OAuth instead of the local one. No credential is stored, because none is needed. |
--scope user |
Write the client's user-level configuration rather than the project's. |
--name <name> |
Name the server something other than myna. |
--key <token> |
Store a specific credential — usually a narrowly scoped API key — instead of the one the CLI resolved. |
--print |
Show exactly what would be written, and write nothing. |
--force |
Replace an existing entry of the same name. |
myna mcp uninstall removes the entry again. It leaves the credential file alone: that credential is shared with any other client still configured, and removing one entry is not a statement about the rest.
Codex is listed but marked (manual) — its configuration is TOML, and merging TOML correctly needs a parser the CLI has no other reason to carry, so myna mcp install codex prints the block to paste rather than editing the file behind your back.
Pair this with myna skills install, which gives the agent the rules the tools exist to enforce.
The rest of this page is what that command writes, for anyone configuring a client by hand or one the CLI does not know about yet.
Claude Code
$ claude mcp add myna --env MYNA_TOKEN=myna_sk_... --env MYNA_ORGANIZATION=my-org --env MYNA_PROJECT=my-project -- npx -y @myna-sh/mcp
Or declare it in the project's .mcp.json (keep real tokens out of source control — reference them from the environment or use the config file described below):
{
"mcpServers": {
"myna": {
"command": "npx",
"args": ["-y", "@myna-sh/mcp"],
"env": {
"MYNA_TOKEN": "myna_sk_...",
"MYNA_ORGANIZATION": "my-org",
"MYNA_PROJECT": "my-project"
}
}
}
}
Cursor and other MCP clients
Cursor (.cursor/mcp.json) and most stdio MCP clients accept the same shape:
{
"mcpServers": {
"myna": {
"command": "npx",
"args": ["-y", "@myna-sh/mcp"],
"env": {
"MYNA_TOKEN": "myna_sk_...",
"MYNA_ORGANIZATION": "my-org",
"MYNA_PROJECT": "my-project"
}
}
}
}
The server reads four environment variables: MYNA_API_URL (defaults to https://api.myna.sh), MYNA_TOKEN, MYNA_ORGANIZATION, and MYNA_PROJECT. When MYNA_PROJECT is set, it becomes the default project for every tool call that omits one.
Use a narrowly scoped key
Create a dedicated API key for the agent instead of reusing a personal credential. A typical agent key grants content:read and content:write but not content:publish, keeping the publish step with a human or a separately-credentialed workflow. Add feedback:read and feedback:write for an agent that works the report queue, and analytics:read for one that has to explain what a change did. project:admin never widens to a product added later; admin:all is the scope that does. See scopes for the catalog and authentication for creating keys.
Multiple named projects
For agents that work across projects, define named configurations in ~/.config/myna/mcp.json (or a file pointed to by MYNA_MCP_CONFIG):
{
"default": "blog",
"apiUrl": "https://api.myna.sh",
"token": "myna_sk_default...",
"projects": {
"blog": { "project": "company-blog", "organization": "my-org" },
"docs": { "project": "docs-site", "organization": "my-org", "token": "myna_sk_docs..." }
}
}
Tool calls can then pass project: "docs" to target a named configuration by name (or pass a raw project id/slug directly). Per-project apiUrl and token override the top-level defaults; environment variables (MYNA_TOKEN, MYNA_API_URL) take precedence over the file's top-level values. default selects the configuration used when a call omits project.
Streamable HTTP mode
By default the server speaks stdio. Pass --http or set MYNA_MCP_TRANSPORT=http to run it as a stateless streamable-HTTP server instead — useful for hosting one shared server for remote agents:
$ MYNA_MCP_TRANSPORT=http \
MYNA_MCP_TOKEN=endpoint-secret \
MYNA_TOKEN=myna_sk_... \
MYNA_PROJECT=my-project \
npx -y @myna-sh/mcp
- The MCP endpoint is
POST /mcp; each request gets a fresh server instance (stateless, no session ids, no standalone SSE stream — non-POST requests get405). GET /healthreturns{"ok": true}for load-balancer checks.- The port is
MYNA_MCP_PORT, thenPORT, then3333.
Note the two-token model: MYNA_MCP_TOKEN protects the HTTP endpoint itself — clients must send it as Authorization: Bearer <token> — while MYNA_TOKEN is the Myna API credential the server uses upstream. Keep them distinct; if MYNA_MCP_TOKEN is unset the server falls back to requiring MYNA_TOKEN as the bearer, which works but conflates the two roles.
This mode is for running your own shared endpoint with a single credential. If you want per-user, OAuth-authorized access for remote agents, use the hosted server — it is part of the API service and needs no separate process.
Stdio vs. HTTP
| stdio (default) | Self-hosted HTTP | Hosted | |
|---|---|---|---|
| Launch | Client spawns npx -y @myna-sh/mcp |
You run and host the process | Nothing to run |
| Credentials | Per-client env or config file | Server-side env; one shared endpoint token | Per-user OAuth grant, or an API key |
| Users | One | All clients share one identity | Each person gets their own revocable grant |
| State | One process per client session | Stateless; fresh server per request | Stateless |
myna_upload_asset |
Accepts base64 or a local file path |
base64 only — the server has no access to the client's filesystem |
base64 only |
Path-based uploads are the main reason to prefer stdio for local coding agents; everything else behaves identically across transports.
