nazanin-mcp
v0.4.0
Published
Stdio MCP server that exposes a Nazanin PLM portfolio to Claude Code — list / read / write URDs, design docs, plans, ADRs, launch checklists, retrospectives, and session notes.
Maintainers
Readme
Nazanin MCP
Stdio MCP server that exposes your Nazanin portfolio to Claude Code.
What it does
Adds 24 tools to your Claude Code sessions — 10 reads, 14 writes:
Read tools
| Tool | What it returns |
|---|---|
| list_projects | All projects (slug, name, status, deploy url, description) |
| get_project | One project + its intake snapshot |
| get_urd | URD markdown body |
| get_design_doc | Design Doc markdown body |
| get_plan | Full plan tree (phases → steps → items) |
| get_adrs | All ADRs with bodies and status |
| get_launch_checklist | Items + done counts |
| get_retrospectives | All retros, newest first |
| get_status_history | Lifecycle transitions over time (from migration 12) |
Write tools
| Tool | What it does |
|---|---|
| update_urd | Replace the URD body (full markdown — not append) |
| update_design_doc | Replace the Design Doc body |
| add_adr | Create a new ADR (auto-numbered) |
| update_project_status | Bump lifecycle status (any of the 13 stages) |
| create_project | Create a new project in the portfolio |
| add_checklist_item | Append an item to the launch checklist |
| update_checklist_item | Flip checked / edit label / set notes on a checklist item |
| save_retrospective | Create or update a retrospective (markdown body) |
| add_plan_phase | Append a phase to a project plan |
| add_plan_step | Append a step under a phase |
| add_plan_item | Append a leaf item under a step |
| set_plan_phase_status | Set phase status (not_started / in_progress / completed) |
| set_plan_step_status | Set step status |
| set_plan_item_status | Set item status (auto-sets completed_at on completed) |
| append_session_note | Log a session note (project-scoped or global) |
With these, you can ask Claude in a future session "what's the URD say about Nazanin's data model?" or "what's left on the Tagverse launch checklist?" without pasting any context.
Install
Quick path (recommended) — npx + npm
End users only need ONE command:
claude mcp add nazanin -s user \
-e SUPABASE_URL=https://YOUR-REF.supabase.co \
-e SUPABASE_SERVICE_ROLE_KEY=eyJ...your-key... \
-e NAZANIN_PAT=naz_xxx...your-token... \
-- npx -y nazanin-mcpRestart Claude Code — done. npx -y nazanin-mcp fetches the latest
published version on each launch, so updates land automatically.
Get a Personal Access Token (recommended)
In the Nazanin web app, open Settings → MCP Tokens, click
Generate, give it a name (e.g. your machine name), and copy
the token. Use it as NAZANIN_PAT in the install command above.
PATs are SHA-256 hashed at rest — they can be revoked individually
from the same settings tab, and the MCP updates last_used_at on
every startup so you can see when each token was last active.
Get your Supabase service-role key
Supabase Dashboard → your Nazanin project → Project Settings → API →
copy service_role (secret, starts with eyJ...).
This key bypasses RLS. Keep it out of any committed file. The MCP
runs locally on your machine only — env vars set via claude mcp add -e
live in Claude Code's config, not in the repo.
Verify
In a new Claude Code session:
/mcpYou should see nazanin listed with 9 tools. Try:
Claude, list my Nazanin projects.
Tool reference
All slug-taking tools accept a project slug from list_projects
(e.g. axions, tagverse, tagflix, nazanin).
list_projects(include_archived?: boolean)
get_project(slug: string)
get_urd(slug: string)
get_design_doc(slug: string)
get_plan(slug: string)
get_adrs(slug: string)
get_launch_checklist(slug: string)
get_retrospectives(slug: string)
get_status_history(slug: string)
create_project(slug: string, name: string, short_name?: string, description?: string, status?: LifecycleStage, github_repo?: string, deploy_url?: string, emoji?: string, color?: string)
update_checklist_item(item_id: string, checked?: boolean, label?: string, section?: string, notes?: string)
save_retrospective(title: string, slug?: string, id?: string, body?: string, launched_at?: string)
add_plan_phase(slug: string, title: string, description?: string)
add_plan_step(slug: string, phase_id: string, title: string, description?: string)
add_plan_item(slug: string, step_id: string, title: string, description?: string)
set_plan_phase_status(phase_id: string, status: PlanStatus)
set_plan_step_status(step_id: string, status: PlanStatus)
set_plan_item_status(item_id: string, status: PlanStatus)
update_urd(slug: string, body: string)
update_design_doc(slug: string, body: string)
add_adr(slug: string, title: string, body?: string, status?: AdrStatus, decided_at?: string)
update_project_status(slug: string, status: LifecycleStage)
add_checklist_item(slug: string, label: string, section?: string)
append_session_note(summary: string, slug?: string, body?: string)LifecycleStage ∈ {idea, intake, refining, urd, design, planning, scaffolding, building, testing, pre_launch, launching, live, sunset}.
AdrStatus ∈ {proposed, accepted, superseded, deprecated}.
PlanStatus ∈ {not_started, in_progress, completed}.
Auth model
The MCP connects to Supabase as service-role (bypassing RLS) and
scopes every query manually with .eq('user_id', userId). The user
identity comes from one of three sources, in priority order:
NAZANIN_PAT— Personal Access Token from Settings → MCP Tokens. Hashed with SHA-256 at startup, looked up inmcp_tokens. The MCP bumpslast_used_aton every match. Revoked or expired tokens error loudly. Recommended path because tokens can be revoked per device without rotating the service-role key.NAZANIN_USER_ID— explicit UUID override. Useful for testing against another user's data in development.- Single-user default — if neither env var is set, the MCP looks
up the only row in
auth.usersand uses it. Errors if zero or multiple users exist.
JWT minting for RLS scoping is intentionally not implemented for this stdio variant — each user runs their own server process behind their own service-role key, so the explicit user_id scoping the queries already do is equivalent. JWT minting would matter only for a hosted multi-tenant MCP where one process serves many users.
Updating
After a code change:
cd mcp
npm run buildNo need to re-register with Claude — the file path stays the same. Restart any open Claude Code session to pick up the new build.
Troubleshooting
- "No auth users found" — sign up at the Nazanin dev server first (or in production at https://nazanin-app.netlify.app/signup).
- "SUPABASE_SERVICE_ROLE_KEY is not set" — re-run
claude mcp addwith the-eflag, or checkclaude mcp listto see the env vars that were captured. - Tools don't appear after restart — run
/mcpto inspect; if the server failed to start, the diagnostic output is in~/Library/Logs/Claude/mcp-server-nazanin.log(macOS).
