Skip to content
Back to skills

Mcp Per Project

ASecurity

Set up or fix per-project MCP isolation in Cursor and Claude Code, so concurrent agent sessions for different products (e.g. Acme vs Globex vs Initech) each get their own Railway, Postgres, Logfire, PostHog, etc. Use when the user mentions MCP bleed across projects, global mcp.json pollution, multiple Railway accounts/tokens on one machine, wants project-scoped MCP servers, or when onboarding a product repo (invoked from the onboard-repo skill).

  • 6 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added September 3, 2026
developmentrustbashreactgitapifrontendbackend

Works with

  • claude code
  • cursor
  • api
  • mcp

Security analysis

A100/100

Scanned September 3, 2026

npx -y skills add dimeloper/second-brain-workflow --skill mcp-per-project --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Mcp Per Project?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Mcp Per Project
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/dimeloper-mcp-per-project/badge)](https://www.skillsdirectory.com/skills/dimeloper-mcp-per-project)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: mcp-per-project
description: >
  Set up or fix per-project MCP isolation in Cursor and Claude Code, so
  concurrent agent sessions for different products (e.g. Acme vs Globex vs
  Initech) each get their own Railway, Postgres, Logfire, PostHog, etc. Use when
  the user mentions MCP bleed across projects, global mcp.json pollution,
  multiple Railway accounts/tokens on one machine, wants project-scoped MCP
  servers, or when onboarding a product repo (invoked from the onboard-repo
  skill).
---

# Per-project MCP

Also run as **step 6 of `onboard-repo`** for every product backend or sibling
app — do not wait for the user to say "MCP".

## Problem

Both agents have a machine-wide MCP scope that every session loads. Putting
`railway` + `railway-acme` there means Globex sessions see Acme tools, and a
single `railway login` fights across accounts.

| | Machine-wide (keep empty of product infra) | Per-project (use this) |
|---|---|---|
| **Cursor** | `~/.cursor/mcp.json` | `<repo>/.cursor/mcp.json` |
| **Claude Code** | user scope, `~/.claude.json` | `<repo>/.mcp.json` (project scope) |

Claude Code also has a *local* scope — project-specific but private to you,
stored outside the repo. Use it for a server you need but shouldn't commit;
`.mcp.json` is the checked-in, team-shared one.

## Rules

1. **Machine-wide scope stays free of product infra.** Cursor: `mcpServers: {}`
   in `~/.cursor/mcp.json`. Claude Code: add nothing with `--scope user`.
   Exception: a genuinely universal, account-agnostic tool.
2. **Each product defines servers in its own repo** — `.cursor/mcp.json` for
   Cursor, `.mcp.json` for Claude Code. Commit `.mcp.json` and
   `.cursor/mcp.json.example`; gitignore `.cursor/mcp.json`.
3. **Name servers with a product suffix**: `railway-acme`, `railway-globex`,
   `railway-postgres-acme`, … Never a bare `railway` when several products share
   the machine. Note Claude Code reserves `workspace`, `claude-in-chrome`,
   `computer-use`, `Claude Preview`, `Claude Browser` — a server with a reserved
   name is skipped at load.
4. **Auth from that repo's `.env`**, not an interactive login:
   - `RAILWAY_TOKEN` — Railway project/environment token for that product only
   - `LOGFIRE_READ_TOKEN` — Logfire **read** token (`project:read`), not the write token
   - `POSTHOG_PERSONAL_API_KEY` — PostHog personal API key (MCP preset)

   Wrappers read `.env` and `exec` the server, so **one wrapper serves both
   agents**. New repos: put them in `.mcp/bin/`, which is agent-neutral.
   Existing repos already using `.cursor/bin/` can stay — it is only a path in
   config, so do not churn working setups.
5. **An always-on rule lists the exact server names** and forbids falling back
   to another product's MCP. This is a rule like any other: author it once and
   let `render.py` emit `.cursor/rules/mcp.mdc` and `.claude/rules/mcp.md`.
6. **Sibling apps** (frontend/mobile/Flutter) point absolute paths at the
   **backend's** wrappers, so a multi-root workspace has one secret source.
7. **Expo / React Native apps** also wire the Expo remote MCP under a suffixed
   name. Auth is OAuth — Cursor Settings → MCP, or `/mcp` in Claude Code (EAS
   paid plan). Keep it project-scoped. Skip on pure web/backend repos.

## Config shapes

Cursor, `<repo>/.cursor/mcp.json`:

```json
{
  "mcpServers": {
    "railway-acme": { "command": "${workspaceFolder}/.mcp/bin/railway-mcp.sh" }
  }
}
```

Claude Code, `<repo>/.mcp.json`:

```json
{
  "mcpServers": {
    "railway-acme": {
      "command": "${CLAUDE_PROJECT_DIR:-.}/.mcp/bin/railway-mcp.sh"
    },
    "expo-acme": {
      "type": "http",
      "url": "https://mcp.expo.dev/mcp"
    }
  }
}
```

Three things that bite:

- An entry with `url` but **no `type`** is a configuration error — Claude Code
  reads it as a stdio server and skips it. Always set `"type": "http"` (or
  `sse` / `ws`) alongside a `url`.
- `${VAR}` and `${VAR:-default}` expand in `command`, `args` and `env` only.
  `${CLAUDE_PROJECT_DIR}` needs the `:-.` default in a project-scoped file.
- Project-scoped servers require approval on first use. `claude mcp list` shows
  `⏸ Pending approval`; run `claude` interactively to approve, or
  `claude mcp reset-project-choices` to start over. A freshly cloned repo cannot
  approve its own servers until you accept the workspace trust dialog.

## Bootstrap a new product

```bash
# In <product>-backend — copy the wiring of the closest already-set-up backend.
# Find candidates:  ls -d ~/*/*/.mcp/bin ~/*/*/.cursor/bin 2>/dev/null
# Match on provider mix, not project name. Two common shapes:
#   full product  — Railway + Postgres + Logfire EU + PostHog
#   infra-light   — Railway prod + staging only
mkdir -p .mcp/bin
# Adapt the wrappers for this product's suffix, then write the config(s) the
# agents on this machine actually use:
#   Cursor       -> .cursor/mcp.json  (+ .cursor/mcp.json.example, gitignore the real one)
#   Claude Code  -> .mcp.json         (committed)
# Append empty RAILWAY_TOKEN / LOGFIRE_READ_TOKEN / POSTHOG_PERSONAL_API_KEY to .env
# Sibling apps: absolute paths -> the backend's wrappers, no local tokens
```

Wrapper shape, unchanged across agents:

```bash
#!/usr/bin/env bash
set -euo pipefail
cd "$(dirname "$0")/../.."
set -a; . ./.env; set +a
exec railway mcp
```

Reload after editing config or tokens: Cursor Settings → MCP → refresh, or
`/mcp` in Claude Code. If tokens are set, smoke-check with a cheap live call
(`whoami`, `SELECT 1`, Logfire schema, PostHog org list) and report ready vs
unauthorized. If tokens are empty, say what to create — do not block onboarding.

## Verify isolation

In an Acme session the available servers include `*-acme` and **not**
`*-globex`, and the reverse in a Globex session. Machine-wide scope lists no
product servers: `claude mcp list` for Claude Code, the global MCP list in
Cursor Settings.

## Do not

- Put product Railway / Postgres / Logfire / PostHog servers in `~/.cursor/mcp.json`
  or in Claude Code's user scope
- Use a bare server name like `railway` when several products share the machine
- Share one `RAILWAY_TOKEN` across products
- Fall back to another product's MCP when the right one is unauthorized
- Commit a config containing real tokens — tokens live in `.env`, referenced by
  the wrapper

## Related

- `onboard-repo` — invokes this as step 6
- Practice note `mcp-per-project` in the vault

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.