# 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](/mcp/hosted) at `https://api.myna.sh/mcp` instead. 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](/mcp/tools) for the full list. Fourteen of those belong to [Feedback](/concepts/reports) and ten to [Analytics](/concepts/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](/concepts/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: ```bash $ 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`: ```bash $ 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](#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](/mcp/hosted) 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 the server something other than `myna`. | | `--key ` | 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`](/agents/skills), 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 ```bash $ 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): ```json { "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: ```json { "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](/platform/scopes) for the catalog and [authentication](/getting-started/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`): ```json { "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: ```bash $ 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 get `405`). - `GET /health` returns `{"ok": true}` for load-balancer checks. - The port is `MYNA_MCP_PORT`, then `PORT`, then `3333`. Note the **two-token model**: `MYNA_MCP_TOKEN` protects the HTTP endpoint itself — clients must send it as `Authorization: Bearer ` — 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](/mcp/hosted) — it is part of the API service and needs no separate process. ## Stdio vs. HTTP | | stdio (default) | Self-hosted HTTP | [Hosted](/mcp/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.