Tag: Developer Reference

  • Connect Claude Code to Postgres via MCP: The Right Way (2026)

    Connect Claude Code to Postgres via MCP: The Right Way (2026)

    The most useful thing you can wire into Claude Code isn’t a new model or a clever prompt — it’s your actual database. When Claude Code can read your schema, it stops guessing at table names, column types, and relationships. It starts writing queries that work the first time.

    This is the practical walkthrough for connecting Claude Code to a Postgres database via MCP: the command, the credential setup, the safety pattern, and what the workflow actually looks like once it’s running.

    What the Postgres MCP server does

    The official @modelcontextprotocol/server-postgres package (maintained in the MCP reference implementations repo) gives Claude Code four tools: schema inspection, query execution inside a read-only transaction, table detail lookup, and relationship traversal. The server cannot write data — it’s read-only by design in the reference implementation, though third-party variants like postgres-mcp-pro add configurable write access if you need it.

    For the majority of development workflows — debugging, writing migrations, generating queries — read-only is exactly what you want. Claude Code can see the shape of your data without being able to touch it.

    The fastest path: single command setup

    If you just want it running against a local database:

    claude mcp add postgres -- npx -y @modelcontextprotocol/server-postgres "postgresql://USER:PASSWORD@localhost:5432/mydb"

    The -y flag on npx auto-accepts the package install so the command doesn’t hang on first run. Verify with:

    claude mcp list

    You should see postgres with a connected status. That’s it — Claude Code now has schema access in the current project.

    Don’t do this for a production database. The connection string above is hardcoded. It goes into ~/.claude.json as plaintext. Use a dedicated local or staging database during development, and use env vars for anything that matters.

    The right way: env vars and a read-only user

    Two things to do before connecting to any real database:

    1. Create a read-only Postgres user:

    CREATE USER claude_readonly WITH PASSWORD 'your-password-here';
    GRANT CONNECT ON DATABASE your_db TO claude_readonly;
    GRANT USAGE ON SCHEMA public TO claude_readonly;
    GRANT SELECT ON ALL TABLES IN SCHEMA public TO claude_readonly;
    ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO claude_readonly;

    This user can see everything in public and do nothing else. If something goes wrong — a rogue tool call, a compromised session — blast radius is zero.

    2. Reference the connection string via env var in .mcp.json:

    {
      "mcpServers": {
        "db": {
          "type": "stdio",
          "command": "npx",
          "args": ["-y", "@modelcontextprotocol/server-postgres"],
          "env": {
            "POSTGRES_CONNECTION_STRING": "${DATABASE_URL}"
          }
        }
      }
    }

    Set DATABASE_URL in your shell environment or in a .env file (not committed). Add .mcp.json to the repo — everyone on the team gets the same server config — but the actual connection string lives in each developer’s local environment. This is the same pattern you already use for application config. It’s the right pattern here too.

    Add the server at project scope so it’s committed:

    claude mcp add --scope project --transport stdio db -- npx -y @modelcontextprotocol/server-postgres

    Then edit .mcp.json to replace the hardcoded connection string with the ${DATABASE_URL} env var reference shown above.

    What Claude Code can actually do with schema access

    Once the server is connected, the workflow changes significantly. A few real examples:

    Schema exploration: Ask Claude Code “what tables are in this database and how are they related?” and it traverses foreign keys, describes join paths, and builds a mental model of your data layer. No more copy-pasting \dt output.

    Query generation: “Write a query that finds users who signed up in the last 30 days but haven’t completed onboarding” produces accurate SQL because Claude Code knows your actual column names. With a generic prompt and no schema access, you’d get plausible-looking SQL that fails because user_status is actually onboarding_state.

    Migration drafting: “I need to add a last_login_at column to users — show me the migration and check for existing timestamp patterns in the schema.” Claude Code inspects the schema first, matches your existing column naming conventions, and produces a migration that fits your codebase.

    Debugging: “This query is returning the wrong count — here’s the query, check it against the schema.” Claude Code can spot that you’re joining on a nullable column, missing a filter on a soft-delete flag, or aggregating before filtering.

    Neon and cloud Postgres

    If you’re on Neon, there’s a first-party MCP server with additional capabilities: branch management, database creation, and schema migrations via Neon’s branching model. Set it up with:

    npx neonctl mcp add

    This runs OAuth through your browser and configures Claude Code automatically. The Neon MCP server is intended for local development and IDE workflows — not production automation — same caution applies.

    Debugging when it doesn’t connect

    Three commands for when the server shows as disconnected:

    claude mcp list          # check registered servers and status
    claude mcp test db       # test a specific server
    claude --debug           # tail logs including MCP stderr output

    Most connection failures are either a wrong connection string, a missing env var, or Node version issues with npx. The debug log shows the exact error from the server process — read it before assuming the problem is Claude Code.

    The practical baseline

    Five minutes to set up. The productivity delta on any codebase larger than a few tables is immediate — Claude Code stops making column-name mistakes and starts being genuinely useful for data-layer work. Wire up the read-only user, commit the .mcp.json, and add DATABASE_URL to your team’s .env.example. Done.

    The model doing the work in a typical Claude Code session is claude-sonnet-4-6 (workhorse) — it handles schema-aware query generation well without burning through Opus 4.8 credits on every lookup.

    Related Reading

    Frequently Asked Questions

    How do I connect Claude Code to a Postgres database via MCP?

    Run: claude mcp add postgres — npx -y @modelcontextprotocol/server-postgres “postgresql://USER:PASSWORD@localhost:5432/mydb”. The -y flag auto-accepts the package install so the command doesn’t hang. Then run claude mcp list and confirm postgres shows a connected status. Use a local or staging database for this quick path, not production.

    Is the Postgres MCP server read-only?

    Yes. The official @modelcontextprotocol/server-postgres package is read-only by design — it exposes schema inspection, query execution inside a read-only transaction, table detail lookup, and relationship traversal. It cannot write data. Third-party variants like postgres-mcp-pro add configurable write access if you need it.

    What’s the safe way to connect Claude Code to a production database?

    Create a dedicated read-only Postgres user (GRANT SELECT only), and reference the connection string through an environment variable in .mcp.json using ${DATABASE_URL} rather than hardcoding it. Commit .mcp.json so the team shares the server config, but keep the actual connection string in each developer’s local .env. If a session is ever compromised, the blast radius is zero.

    Why does schema access make Claude Code more accurate?

    With schema access, Claude Code reads your real table names, column types, and relationships, so it writes queries that work the first time instead of guessing. Without it, you get plausible-looking SQL that fails because user_status is actually onboarding_state. It also improves migration drafting and query debugging by matching your existing conventions.

    How do I debug a Postgres MCP server that won’t connect?

    Use three commands: claude mcp list to check registered servers and status, claude mcp test db to test a specific server, and claude –debug to tail logs including MCP stderr. Most failures are a wrong connection string, a missing env var, or a Node version issue with npx — the debug log shows the exact server error.

  • Notion MCP Setup with Claude: Complete Config + the Errors Nobody Documents

    Notion MCP Setup with Claude: Complete Config + the Errors Nobody Documents

    Last verified: June 2026.

    There are two ways to connect Notion to Claude over the Model Context Protocol (MCP), and almost every tutorial only covers one of them. Worse, none of them tell you why the connection succeeds but Claude still says it cannot find any of your pages. This guide covers both paths – the hosted OAuth connector and the self-hosted token route – with the exact config, the scopes that matter, the rate limit you will hit, and the specific error strings that show up when something is wrong. It is written from actually running this, not from reading the docs.

    Which Notion MCP should you use: hosted or self-hosted?

    Short answer: use the hosted MCP at https://mcp.notion.com/mcp for almost everything. It uses OAuth, so you never handle a token, and it respects your existing Notion permissions automatically. Use the self-hosted npm server with an internal integration token only when you need headless, unattended automation (a cron job, a server with no human to click “Allow”), because the hosted server requires an interactive OAuth approval that a background process cannot complete.

    Factor Hosted (mcp.notion.com) Self-hosted (npm + token)
    Auth OAuth (interactive) Internal integration token (ntn_)
    Permissions Inherits your full Notion access Only pages you explicitly share
    Setup time ~2 minutes ~10 minutes
    Headless / cron No (needs a human to approve) Yes
    Best for Claude Desktop, Claude Code, daily use Servers, scripts, multi-user backends

    How do I connect Notion to Claude using the hosted MCP?

    This is the fast path. No token, no npm.

    Claude Desktop / Claude.ai: Open Settings > Connectors, click Add custom connector (or pick Notion if it appears in the directory), and paste the URL https://mcp.notion.com/mcp. A Notion OAuth window opens. Approve it, choose which workspace and which top-level pages the connector may see, and you are done. The scope you pick in that OAuth screen is the whole ballgame – see the gotcha below.

    Claude Code (CLI): one command.

    claude mcp add --transport http notion https://mcp.notion.com/mcp

    Then run /mcp inside Claude Code to trigger the OAuth login. After approving, verify it is live:

    claude mcp list

    You should see notion with a connected status. If it shows failed or needs auth, run /mcp again and complete the browser flow – the CLI cannot proceed past OAuth on its own.

    How do I set up the self-hosted Notion MCP with an integration token?

    Use this when you need automation that runs without a human. Three steps: create the integration, get the token, then wire it into your MCP config.

    1. Create the integration and copy the token

    1. Go to https://www.notion.so/my-integrations and click New integration. You must be a Workspace Owner – if the button is greyed out, that is why.
    2. Name it, select the workspace, and choose Internal integration type.
    3. On the integration’s settings page, set Capabilities: Read content, plus Update/Insert content if you want Claude to write. If you only grant Read, every write attempt fails with a permission error later – this is a common self-inflicted wound.
    4. Click Show, then copy the Internal Integration Token. New tokens start with ntn_ (older ones start with secret_ and still work). Treat it like a password.

    2. Add it to your MCP config

    For Claude Desktop, edit claude_desktop_config.json (macOS: ~/Library/Application Support/Claude/; Windows: %APPDATA%\Claude\). Add:

    {
      "mcpServers": {
        "notion": {
          "command": "npx",
          "args": ["-y", "@notionhq/notion-mcp-server"],
          "env": {
            "NOTION_TOKEN": "ntn_your_token_here"
          }
        }
      }
    }

    Restart Claude Desktop completely (quit, do not just close the window). On Windows, if npx is not found, use the full path to npx.cmd or run via cmd /c – the config does not inherit your shell PATH.

    3. The step everyone forgets: share the pages

    An internal integration starts with access to nothing. Creating it and pasting the token is not enough. For every page or database you want Claude to touch, open it in Notion, click the menu (top right), choose Connections (or Add connections), and select your integration. Access is inherited by child pages, so sharing a top-level page covers its whole subtree. Skip this and Claude will connect cleanly and then truthfully report that it cannot see any content.

    What are the most common Notion MCP errors and how do I fix them?

    These are the failure messages you will actually see, and what each one means.

    “Could not find page” / Claude returns zero results from a workspace that clearly has pages

    Cause, in order of likelihood: (1) you did not share the page with the integration (self-hosted), or you scoped the OAuth grant too narrowly (hosted); (2) the page is in a different workspace than the one the integration is tied to. Fix: re-check the Connections menu on the specific page, or re-run the OAuth flow and widen the page selection. An integration token is bound to one workspace – it cannot see another.

    API token is invalid (HTTP 401 unauthorized)

    The token is wrong, was regenerated, or has a stray space/newline from copy-paste. Re-copy it with the Show button, paste it into the env block with no surrounding whitespace, and restart the client. If you rotated the token in Notion, the old one dies immediately – update every config that used it.

    Validation error / “body failed validation” (HTTP 400)

    Claude tried to write a property type that does not match the database schema – for example sending plain text into a Select, or a malformed date. This is not a connection problem. Tell Claude the exact property names and types, or ask it to fetch the database schema first before writing.

    “Rate limited” / HTTP 429

    Notion enforces roughly 3 requests per second per integration (averaged, with short bursts tolerated). Bulk operations – “update 200 rows,” “scan every page” – blow straight through this. The fix is pacing, not a bigger plan: have Claude batch in small groups and add a short delay between calls. If you are scripting around the MCP, honor the Retry-After header on a 429 instead of hammering.

    spawn npx ENOENT (server will not start, self-hosted)

    Node/npx is not on the PATH the client sees. Install Node, then point command at the absolute path to npx (or npx.cmd on Windows). This is the number-one self-hosted startup failure.

    MCP server shows “failed” in claude mcp list right after adding it

    For the hosted server this almost always means OAuth was never completed – run /mcp and approve in the browser. For the self-hosted server it means the process crashed on launch; run the npx command manually in a terminal to see the real stack trace.

    What can Claude actually do with Notion once connected?

    With read + write capabilities granted, Claude can search your workspace, read pages and databases, create pages, append blocks, and update properties on existing rows. Practical things that work well: “summarize this Notion doc,” “create a row in my tasks database with these fields,” “find every page mentioning X and list the links,” “turn this conversation into a meeting-notes page.” Things that get awkward: very large pages (the response can get truncated – verify the write actually landed by fetching it back), and bulk edits that trip the rate limit. A reliable habit is to treat Notion as the source of truth and have Claude verify by re-fetching after any write, because timeouts on big pages can commit silently and still return a malformed response.

    Security notes from running this in production

    • Scope the OAuth grant tightly. The hosted connector inherits whatever you approve. If you only need one project area, share only that top-level page, not the whole workspace.
    • Never hardcode the token in a file you might commit. Keep ntn_ tokens in an env var or your OS secret store, and reference them from config. If a token leaks, revoke it in my-integrations immediately – revocation is instant.
    • Grant the minimum capability. If Claude only needs to read, do not enable insert/update. You can always widen it later.
    • Audit which integrations have access to sensitive databases periodically; the Connections menu on each page shows the current list.

    If you are wiring up several connectors at once, the mechanics generalize – see our broader Claude MCP setup guide for the config patterns that apply across servers, and the AI operator’s stack for how Notion fits alongside the other tools day to day. If your reason for connecting Notion is to get your own content cited by AI systems, the structure of the pages matters as much as the wiring – see how AI engines cite content.

    FAQ

    Do I need a paid Notion plan to use the MCP?

    No. The API and integrations work on free Notion workspaces. You do need to be a Workspace Owner to create an internal integration.

    Why does Claude say it connected but can’t find my pages?

    Almost always the page-sharing step. A self-hosted integration has access to nothing until you add it via the page’s Connections menu. For the hosted connector, you scoped the OAuth approval too narrowly – re-run it and select more pages.

    What is the Notion API rate limit?

    About 3 requests per second per integration, averaged over time with small bursts allowed. Exceeding it returns HTTP 429. Pace bulk operations and respect the Retry-After header.

    What does the ntn_ prefix mean on my token?

    It is the current internal integration token format. Tokens created today start with ntn_; older secret_ tokens still function and do not need to be replaced.

    Can the hosted Notion MCP run in a headless cron job?

    No. The hosted server requires interactive OAuth approval, which an unattended process cannot complete. Use the self-hosted npm server with an ntn_ token for headless automation.

    How do I let Claude write to Notion, not just read?

    Enable Update content and Insert content under the integration’s Capabilities (self-hosted), or approve write scope during OAuth (hosted). Read-only is the default and will reject every write with a permission error.

    Where do I put the Notion MCP config for Claude Desktop?

    In claude_desktop_config.json~/Library/Application Support/Claude/ on macOS, %APPDATA%\Claude\ on Windows. Add a notion entry under mcpServers and fully restart the app.

    Can one integration access two workspaces?

    No. An internal integration is bound to the single workspace it was created in. For a second workspace, create a second integration (or a second OAuth grant on the hosted connector).

    Related reading from operators who run AI tooling daily: Claude Code vs Cursor, Claude Code vs Codex, and Claude in Chrome for LinkedIn automation.

    Frequently Asked Questions

    What is the Notion MCP server for Claude?

    The Notion MCP server is a connector that lets Claude read, search, and interact with your Notion workspace through the Model Context Protocol. With it connected, you can ask Claude to find pages, summarize databases, draft content into Notion, or retrieve information — all without copying and pasting anything manually.

    What is the difference between the Notion OAuth connector and the self-hosted token route?

    The OAuth connector (available in Claude Desktop’s built-in integrations) is the fastest path — authorize once and Claude gets read access to pages you share with the integration. The self-hosted route uses a Notion Internal Integration token in your claude_desktop_config.json, giving you more control over scopes and works in Claude Code environments where OAuth connectors aren’t available.

    Why does Claude say it can’t find my Notion pages after connecting?

    The most common reason is that you haven’t shared the specific pages or databases with your Notion integration. Notion’s permission model requires explicit page-level grants — a successful connection does not automatically give access to all your content. Go to the page in Notion, click the three-dot menu, choose ‘Add connections’, and select your integration.

    What scopes does the Notion MCP integration need?

    For read operations: Read content and Read user information. For write operations: Update content and Insert content. Avoid requesting more scopes than you need — the minimum set reduces the blast radius if a token is ever compromised. Set scopes when creating your Notion Internal Integration at notion.so/my-integrations.

    Does the Notion MCP integration work with Claude Code?

    Yes. Add it via ‘claude mcp add notion npx @notionhq/notion-mcp-server’ and set your NOTION_API_KEY as an environment variable. Claude Code picks it up on the next session. The self-hosted token route works in both Claude Desktop and Claude Code; the OAuth connector is currently Desktop-only.

    What rate limits does the Notion API have?

    Notion’s API enforces a rate limit of 3 requests per second per integration. For typical conversational use this is invisible, but if you ask Claude to crawl a large database or process many pages in sequence, you may see 429 errors. The fix is to add a short sleep between bulk operations or use Notion’s pagination to fetch in smaller batches.


  • How to Connect Any Tool to Claude with MCP: Complete Setup Guide

    How to Connect Any Tool to Claude with MCP: Complete Setup Guide

    Last verified: June 2026

    MCP (Model Context Protocol) is how you give Claude hands. Out of the box Claude can talk; with an MCP server connected, it can read your files, query a database, hit an API, or drive a browser. This guide covers the two places you actually wire servers up: the claude_desktop_config.json file for the Claude Desktop app, and the claude mcp add command for Claude Code (the terminal/IDE tool). It ends with the troubleshooting section the official docs skip: path problems, JSON syntax traps, servers that silently never load, and the Windows quirks that cost people an afternoon.

    Everything below is checked against the current Claude Code MCP docs and tested commands. If you want the wider picture of how MCP fits into a working setup, see the AI operator’s stack.

    What is MCP and what is an MCP server?

    MCP transport options at a glance

    Transport Use case Config location Works with
    stdio Local tools, CLIs, scripts claude_desktop_config.json or claude mcp add Claude Desktop, Claude Code
    SSE (HTTP) Remote servers, cloud services URL in config Claude Desktop, Claude Code
    Streamable HTTP Production remote MCP URL in config Claude Desktop, Claude Code

    MCP is an open standard for connecting AI models to external tools and data. An MCP server is a small program that exposes a set of tools (functions Claude can call) over that protocol. Claude is the client; the server is the thing that actually does the work, like reading a Postgres table or creating a GitHub issue.

    There are two transport types you will deal with in practice:

    • stdio (local): the server runs as a process on your machine. Claude talks to it over standard input/output. Best for filesystem access, local databases, and custom scripts. This is what most “install this MCP server” instructions mean.
    • HTTP (remote): the server lives on the internet at a URL. Best for cloud services (Notion, Sentry, Stripe, GitHub). Often uses OAuth. SSE is the older remote transport and is now deprecated; use HTTP for new remote servers.

    The same server can usually be added to both Claude Desktop and Claude Code. The mechanics differ: Desktop uses a JSON file you edit by hand, Claude Code gives you a CLI that writes the config for you.

    How do I add an MCP server to Claude Desktop?

    Claude Desktop reads a single JSON file. You edit it, fully quit the app, and reopen. There is no in-app “add server” button for custom servers as of June 2026, so the file is the source of truth.

    Where is claude_desktop_config.json?

    • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json
    • Windows: %APPDATA%\Claude\claude_desktop_config.json (paste that into the File Explorer address bar; it expands to C:\Users\YOU\AppData\Roaming\Claude\)

    The fastest way to open it: in Claude Desktop go to Settings > Developer > Edit Config. That button creates the file if it does not exist and opens the folder. If the file is brand new it may be empty or just {}.

    The config file structure

    Everything lives under a top-level mcpServers object. Each key is a name you choose; each value describes how to launch the server. Here is a complete, working file with a local filesystem server and a remote Notion server:

    {
      "mcpServers": {
        "filesystem": {
          "command": "npx",
          "args": [
            "-y",
            "@modelcontextprotocol/server-filesystem",
            "C:\\Users\\YOU\\Documents"
          ]
        },
        "notion": {
          "command": "npx",
          "args": ["-y", "@notionhq/notion-mcp-server"],
          "env": {
            "NOTION_TOKEN": "secret_your_token_here"
          }
        }
      }
    }

    Three fields do all the work:

    • command the executable to run (npx, node, python, uvx, or an absolute path to a binary).
    • args an array of arguments. Each flag and value is its own array element. "--port 8080" as a single string will not work; use "--port", "8080".
    • env an object of environment variables (API keys, tokens). Optional.

    After saving, completely quit Claude Desktop (on Windows, right-click the system tray icon and choose Quit; closing the window is not enough) and reopen it. You should see a tools/connector indicator in the chat input. For a full Notion walkthrough including the token, see connecting Notion to Claude with MCP.

    How do I add an MCP server to Claude Code (CLI)?

    Claude Code does not make you hand-edit JSON. The claude mcp command manages servers for you and writes to the right file. This is the part people get wrong most often, so here is the exact, verified syntax.

    claude mcp add

    The general form for a local (stdio) server is:

    claude mcp add [options] <name> -- <command> [args...]

    The -- is load-bearing. Everything before it is for Claude Code; everything after it is the command that launches your server. Real examples:

    # Local filesystem server
    claude mcp add filesystem -- npx -y @modelcontextprotocol/server-filesystem ~/Documents
    
    # Local server with an environment variable
    claude mcp add --env AIRTABLE_API_KEY=YOUR_KEY airtable -- npx -y airtable-mcp-server
    
    # Remote HTTP server
    claude mcp add --transport http notion https://mcp.notion.com/mcp
    
    # Remote HTTP server with an auth header
    claude mcp add --transport http github https://api.githubcopilot.com/mcp/ --header "Authorization: Bearer YOUR_PAT"

    Option ordering matters. All flags (--transport, --env, --scope, --header) must come before the server name. Put a flag after the name and you will get a confusing parse error or the flag will be passed to your server instead of to Claude Code.

    Scopes: local, project, user

    The --scope flag decides where the config is written and who sees it:

    • local (the default) loads only in the current project, private to you. Stored in ~/.claude.json keyed by the project path.
    • project loads in the current project and is shared with your team. Stored in a .mcp.json file at the project root that you commit to git.
    • user loads across all your projects, private to you. Also stored in ~/.claude.json.
    # Available across all your projects
    claude mcp add --scope user --transport http sentry https://mcp.sentry.dev/mcp
    
    # Shared with your team via .mcp.json in the repo
    claude mcp add --scope project filesystem -- npx -y @modelcontextprotocol/server-filesystem .

    When the same server name exists at multiple scopes, local wins over project, which wins over user. The whole entry from the winning scope is used; fields are not merged.

    claude mcp list, get, and remove

    # List every configured server and its connection status
    claude mcp list
    
    # Show the full config for one server
    claude mcp get github
    
    # Remove a server
    claude mcp remove github

    claude mcp list is your first diagnostic. It shows each server as connected, pending, or failed. Project-scoped servers from a .mcp.json you have not approved yet show as Pending approval until you run claude interactively and accept them.

    Other useful commands

    # Add from a raw JSON blob (handy when copying from a server's README)
    claude mcp add-json weather '{"type":"stdio","command":"npx","args":["-y","weather-mcp"]}'
    
    # Import everything you already set up in Claude Desktop (macOS / WSL)
    claude mcp add-from-claude-desktop

    Inside a running Claude Code session, type /mcp to see live server status, tool counts, and to trigger OAuth login for remote servers that need it.

    Troubleshooting: the errors the docs skip

    Most MCP failures are not exotic. They are paths, quoting, and the app not restarting. Work this list top to bottom.

    Server not loading / no tools appear

    1. Did you actually restart? Claude Desktop only reads the config at launch. Fully quit (tray icon > Quit on Windows, Cmd+Q on macOS) and reopen. In Claude Code, run claude mcp list to see the real status instead of guessing.
    2. Is the command on PATH? The single most common stdio failure is npx, node, python, or uvx not being found by the app. GUI apps often have a narrower PATH than your terminal. Fix it by using an absolute path. Find it with which npx (macOS/Linux) or where npx (Windows), then put that full path in command.
    3. Read the logs. Claude Desktop writes per-server logs. macOS: ~/Library/Logs/Claude/. Windows: %APPDATA%\Claude\logs\. Look for mcp-server-NAME.log. The actual error (missing module, bad token, wrong path) is almost always sitting right there.

    spawn ENOENT or “command not found”

    This means the OS could not find the executable named in command. It is a PATH problem, not a Claude problem. Use the absolute path (see above). On Windows specifically, see the npx note below.

    JSON syntax errors (the silent killer)

    If claude_desktop_config.json has a single syntax error, Claude Desktop loads zero servers and usually says nothing. The usual culprits:

    • Trailing commas. JSON forbids a comma after the last item in an object or array. "args": ["a", "b",] is invalid.
    • Smart quotes. If you edited the file in a word processor, curly quotes (the slanted kind) break the parser. Use a code editor and straight quotes only.
    • Unescaped Windows backslashes. In JSON, \ is an escape character, so every backslash in a Windows path must be doubled: C:\\Users\\YOU\\Documents. A single backslash silently corrupts the string.

    Paste the whole file into any JSON validator before restarting. Thirty seconds there saves an hour of staring.

    Claude Code: flag passed to the wrong place

    If claude mcp add behaves strangely, you almost certainly put a flag after the server name or forgot the --. Reread the order: claude mcp add [flags] NAME -- COMMAND ARGS. The -- separates Claude Code’s flags from your server’s command.

    Windows quirks

    • npx needs a wrapper in some setups. If a bare "command": "npx" fails on Windows, launch it through cmd: "command": "cmd" with "args": ["/c", "npx", "-y", "the-server-package"]. This resolves a class of “npx works in my terminal but not in Claude” failures.
    • Use the right config root. It is %APPDATA%\Claude\ (which is AppData\Roaming), not AppData\Local. Mixing these up means you are editing a file the app never reads.
    • Git Bash mangles paths. If you run commands through Git Bash, it can rewrite paths like /c/Users or absolute paths inside arguments. Prefer PowerShell or cmd for claude mcp add, or pass paths exactly as Windows expects them.
    • WSL is a separate world. A server installed inside WSL is not visible to a Windows-native Claude Desktop, and vice versa. Keep both on the same side.

    Remote server returns 401 / 403

    The server needs authentication. In Claude Code, run /mcp and complete the OAuth flow in your browser. If you hardcoded an Authorization header and it is rejected, the token is wrong for that endpoint; remove the header and let OAuth handle it instead.

    Frequently asked questions

    What is an MCP server in one sentence?

    A small program that exposes tools (functions like read-file or query-database) to Claude over the Model Context Protocol, so Claude can take real actions instead of only producing text.

    What is the difference between Claude Desktop and Claude Code for MCP?

    Claude Desktop is the chat app and you configure servers by hand-editing claude_desktop_config.json, then restarting. Claude Code is the terminal/IDE tool and you configure servers with the claude mcp add command, which writes the config for you.

    Where is the Claude Desktop config file?

    macOS: ~/Library/Application Support/Claude/claude_desktop_config.json. Windows: %APPDATA%\Claude\claude_desktop_config.json. The quickest way to open it is Settings > Developer > Edit Config inside the app.

    Why is my MCP server not showing up?

    In order of likelihood: you did not fully restart the app, the command is not on the app’s PATH (use an absolute path), or there is a JSON syntax error such as a trailing comma, a smart quote, or an unescaped Windows backslash. Check the per-server log in the Claude logs folder for the exact error.

    What does the double dash do in claude mcp add?

    The -- separates Claude Code’s own flags from the command that launches your server. Flags like --transport and --env go before it; the actual launch command (npx -y some-server) goes after it.

    What is the default scope for claude mcp add?

    local. The server loads only in the current project and stays private to you. Use --scope user to make it available in every project, or --scope project to share it with your team via a committed .mcp.json.

    Is SSE or HTTP the right transport for remote servers?

    HTTP. SSE still works but is deprecated. Use --transport http for any new remote server unless its documentation specifically requires SSE.

    How do I remove an MCP server?

    In Claude Code, run claude mcp remove NAME. In Claude Desktop, delete that server’s entry from the mcpServers object in claude_desktop_config.json and restart the app.

    Where to go next

    Once your servers connect cleanly, the leverage comes from using them well. For how this fits a daily workflow, read the AI operator’s stack; if you are choosing between coding environments, see Claude Code vs Cursor. And if you want a concrete first server to wire up, the Notion MCP setup is a clean, high-value place to start.

    Frequently Asked Questions

    What is MCP and why does it matter for Claude?

    MCP (Model Context Protocol) is an open standard that lets Claude connect to external tools, databases, APIs, and services. Without MCP, Claude can only work with text in the conversation window. With an MCP server connected, Claude can read your files, query a live database, hit an API, or control a browser — turning it from a chat interface into an autonomous agent.

    How do I add an MCP server to Claude Desktop?

    Edit the claude_desktop_config.json file (found at ~/Library/Application Support/Claude/ on Mac, %APPDATA%/Claude/ on Windows). Add your server under the ‘mcpServers’ key with a ‘command’, ‘args’, and optional ‘env’ block. Save the file and restart Claude Desktop. The server appears in Claude’s tool list if it loaded correctly.

    How do I add an MCP server to Claude Code?

    Run ‘claude mcp add [args…]’ from your terminal. For a remote SSE server use ‘claude mcp add –transport sse ‘. List configured servers with ‘claude mcp list’. Servers added this way are scoped to your user profile unless you use the –project flag.

    Why does my MCP server connect but Claude can’t see my data?

    The most common cause is scope or permission gaps. For Notion, verify your integration has been granted access to the specific pages/databases — the connection succeeds even without page access. For file servers, check that the path in your config resolves correctly from the shell Claude launches (not your interactive shell). For OAuth servers, re-authorize and confirm token scopes.

    What is the difference between stdio and SSE MCP transports?

    stdio runs the MCP server as a local subprocess — Claude launches the command you specify and communicates over stdin/stdout. This is used for local tools and CLIs. SSE (Server-Sent Events) connects to a remote HTTP server. Use stdio for local tools like filesystem access or database clients; use SSE or Streamable HTTP for cloud services or shared team servers.

    Which MCP servers should I start with?

    The highest-value first connections are: filesystem (read/write your local files), a database client for your primary DB, and a service you interact with daily (Notion, Slack, GitHub, Linear). The Notion MCP server is a clean first project — see the dedicated setup guide on this site for the exact config and common errors.


  • The Top Claude 4.6 Prompt for React Developers This Week

    The Top Claude 4.6 Prompt for React Developers This Week

    The Top Claude 4.6 Prompt for React Developers This Week

    If you are building front-end applications, you already know that Claude 4.6 Sonnet’s context window can handle massive files. But how do you prevent the model from ‘lazy coding’ (leaving // rest of code here comments)?

    The Anti-Lazy Prompt:

    “You are a Senior Staff Engineer. Rewrite this entire React component. Under NO circumstances are you allowed to use placeholders, comments like ‘// existing code’, or brevity. You must output the entire, complete, and fully functional file from line 1 to EOF. Failure to do so will break the CI/CD pipeline.”

    Why it works: By framing the omission as a pipeline-breaking failure, Claude’s alignment training prioritizes the completion of the file over token conservation.

  • Claude Artifacts API Release: What We Are Hearing

    Claude Artifacts API Release: What We Are Hearing

    The Claude “Artifacts” Wrapper is Coming to the Core API

    Anthropic’s “Artifacts” feature—which allows Claude to instantly render and preview code, diagrams, and UI elements in a side panel—has revolutionized the ChatGPT-style web interface. But for developers building their own applications using the Claude API, they’ve been forced to build those UI rendering wrappers from scratch.

    According to emerging chatter on X (Twitter), that is about to change.

    Social Radar Intel:
    “Rumors circulating that the Artifacts UI wrapper is finally coming to the core API next week. If developers can render interactive React components directly inside their own chat UIs using Claude, it’s game over for generic wrappers.”

    Why This Matters for Builders

    If Anthropic exposes the Artifacts rendering engine natively through the API, it significantly lowers the barrier to entry for building rich, interactive AI tools. You will no longer need a senior front-end engineer to parse JSON and render a React component on the fly; the API will handle the interactive framing.

    The Tygart Verdict: We are keeping a close eye on the official Anthropic changelog over the next two weeks. If this drops, expect a flood of “wrapper” apps to pivot or die.

  • The 5-Layer OpenRouter Mental Model: Org, Workspace, Guardrail, Key, Preset

    The 5-Layer OpenRouter Mental Model: Org, Workspace, Guardrail, Key, Preset

    The OpenRouter hierarchy in one sentence: Organizations contain Workspaces, Workspaces enforce Guardrails on API Keys, Keys call Presets, and Presets bundle prompts and models. Every operational decision you’ll ever make on the platform lives at exactly one of those five layers. Confuse them and you’ll spend hours looking for settings that live somewhere other than where you think.

    This is a companion to our OpenRouter operator’s field manual. The field manual covers why we use the platform and how it fits a fortress stack. This deep dive covers the mental model itself — the five-layer hierarchy that makes everything else legible.

    Why this matters before anything else

    OpenRouter’s UI presents a flat menu. The actual product is a hierarchy. Every operational decision you’ll ever make — who pays, what’s allowed, who’s allowed to call what, which model gets used — lives at exactly one of five layers. Get the layers wrong and you’ll wire your stack against the wrong nouns.

    The five layers, top to bottom: Organization → Workspace → Guardrail → API Key → Preset.

    Here’s what each one actually does and when you should care.

    Layer 1: Organization

    Sovereign billing. Sovereign member context. The top of the world.

    Each Organization has its own balance, its own billing details, and — critically — its own member roster. The catch: personal orgs don’t expose Members management. If you want to add teammates, you need a non-personal org.

    In our case we run two: a personal org tied to our primary email, and a Tygart Media org for agency operations. The personal org has 48 API keys and a working balance. The Tygart Media org is empty so far. Members management is the reason it exists.

    When to think about this layer: when you’re deciding whether to operate as an individual or as a team. If you’re solo and plan to stay solo, one personal org is fine forever. The moment you bring on a collaborator who needs their own keys and their own observability slice, you need a non-personal org.

    The mistake to avoid: running an agency out of a personal org. You’ll hit member-management limits at the worst possible time.

    Layer 2: Workspace

    Segmented guardrail, BYOK, routing, and preset domains inside an organization.

    By default, every org gets one Default Workspace. Most accounts never think about this layer. The moment you operate across multiple businesses with different data policies, multiple workspaces become valuable.

    Example: a healthcare client’s data should never touch first-party Anthropic, only Bedrock or Vertex. A consumer comedy site can use any provider. A B2B SaaS client wants Zero Data Retention enforced on every call. Three different fortress postures. Three workspaces.

    Each workspace gets its own Guardrail config, its own BYOK provider keys, its own routing defaults, and its own preset library. Keys created in one workspace can’t see resources in another.

    When to think about this layer: when you have two or more clients with materially different data policies. If everything you do has the same posture, one workspace is fine.

    The mistake to avoid: assuming workspace segmentation is a security boundary. It isn’t, exactly — it’s a policy boundary. Someone with org-level access can move between workspaces freely. Workspaces are for organizing intent, not for isolating threats.

    Layer 3: Guardrails

    The actual enforcement layer. Four categories, all configurable per workspace, all unconfigured by default.

    Budget Policies are the most useful and the most underused. Set a credit limit in dollars and a reset cadence (Day, Week, Month, Year, or N/A). Hit the limit and calls fail until the cadence resets. This is your protection against the runaway loop that drains a balance overnight.

    Model and Provider Access is where data-policy posture lives. Toggles for Zero Data Retention enforcement, Non-frontier ZDR, first-party Anthropic on or off (with Bedrock and Vertex always staying available), first-party OpenAI on or off (Azure stays), Google AI Studio on or off (Vertex stays), and three categories of paid and free endpoints with different training and publishing behaviors. There’s also an Access Policy mode (Allow All Except is the useful one) with explicit Blocked Providers and Blocked Models lists. The live Eligibility view shows you which providers and models are actually callable given your current policy.

    Prompt Injection Detection runs regex-based detection on inbound prompts. OWASP-inspired patterns. Four modes: Disabled, Flag, Redact, or Block. Free and adds no measurable latency. Worth enabling on every workspace that touches user input.

    Sensitive Info Detection runs pattern matching on prompts and completions. Built-in patterns for Email, Phone, SSN, Credit Card, IP address, Person Name, and Address. The latter two add latency. Custom regex patterns supported. A sandbox to test patterns before deploying. Useful for any workspace that processes customer data.

    When to think about this layer: every workspace, day one. Default-unconfigured is not a safe state. Set a budget cap before you do anything else.

    The mistake to avoid: treating Guardrails as something you’ll get to “later.” Later is after the runaway loop has drained the balance.

    Layer 4: API Keys

    Per-agent identity. Each key has its own credit cap, its own reset cadence, and its own guardrail overlay.

    The mental model that matters: one autonomous behavior, one key. When a scheduled task starts hemorrhaging tokens, the cap on its key contains the damage. The other 47 keys keep working.

    Our 48-key distribution is instructive. One testing key has spent $83.26. One development key has spent $33.05. The remaining 46 keys have collectively spent less than $120. That’s the shape of real AI operations: a few keys do most of the work, and a long tail barely moves the needle. Per-key caps make that distribution visible and bounded.

    API keys also carry the BYOK relationship. A bring-your-own provider key can be pinned to specific API keys, meaning specific agents. That lets you route a high-volume internal agent through a discounted enterprise contract while letting one-off testing keys fall through to OpenRouter’s pooled pricing. We cover this in depth in BYOK on OpenRouter.

    When to think about this layer: when you create any new autonomous behavior. New behavior, new key, new cap. No exceptions.

    The mistake to avoid: sharing one key across all your services. The first runaway loop will be the last thing that one key ever does, and the blast radius will be everything else that depended on it.

    Layer 5: Presets

    Versioned bundles of system prompt, model, parameters, and provider configuration. Called as "model": "@preset/your-preset-name" in any API call.

    Three tabs per preset: Configuration (the actual bundle), API Usage (how it’s been called), and Version History (every change, rollback-able).

    This is the closest OpenRouter comes to a software release artifact. You can ship a preset, test it in chat, version it, and roll back if v2 turns out to be worse than v1. Code that calls the preset stays the same; only the preset content changes.

    For autonomous behavior systems this is the unlock. A behavior’s behavior — its prompt, its model choice, its temperature — becomes a thing you can version and review like code, without touching the code that calls it. Promotion ledger says a behavior is graduating from one tier to the next? You publish a new preset version with tighter constraints and the calling code never changes.

    When to think about this layer: the moment you have any system prompt that’s used in more than one place, or that you’ll want to refine over time. If you’ve never copy-pasted a system prompt between two scripts, you don’t need presets yet.

    The mistake to avoid: putting the system prompt in the calling code. Every prompt update becomes a deploy. With presets, prompt updates become config changes.

    Putting the layers together

    Here’s the mental model in one sentence: Organizations contain Workspaces, Workspaces enforce Guardrails on Keys, Keys call Presets, Presets bundle prompts and models.

    If you walk into OpenRouter looking for a setting and you can’t find it, ask which of the five layers it should logically live at. The answer almost always tells you where to look.

    If you’re building a new integration, start at the bottom. Pick a model. Build a preset around it. Create a dedicated key with a tight budget cap. Sit that key under a workspace with sensible guardrails. The organization is just the billing wrapper.

    The whole point of the hierarchy is that each layer constrains the one below it. The organization caps the workspace. The workspace caps the keys. The keys cap the presets they can call. Errors propagate up; permissions cascade down. That’s the model. Everything else is UI.

    Frequently asked questions

    What are the five layers of OpenRouter?

    Organization, Workspace, Guardrails, API Keys, and Presets. Organizations handle billing and members. Workspaces segment policy domains. Guardrails enforce budget, provider access, prompt injection, and sensitive info rules. API Keys are per-agent identity with per-key caps. Presets are versioned bundles of system prompt, model, and parameters.

    Do I need multiple Workspaces in OpenRouter?

    Only if you operate across businesses with materially different data policies. A single Default Workspace is fine for most accounts. The moment a healthcare client requires Bedrock-only access while a consumer client can use any provider, workspace segmentation becomes valuable.

    What is the right way to use OpenRouter Presets?

    Treat them like software release artifacts. Bundle the system prompt, model, parameters, and provider config. Version every change. Test new versions in chat before promoting. Code that calls the preset stays the same; only the preset content evolves. This lets you refactor prompt behavior without redeploying.

    Are OpenRouter Workspaces a security boundary?

    No. They’re a policy boundary, not a security boundary. Someone with organization-level access can move between workspaces freely. Use workspaces to organize intent and enforce different fortress postures across clients — not to isolate threats from each other.

    What happens if I don’t configure OpenRouter Guardrails?

    By default every workspace has zero enforced budget cap, zero provider restrictions, and zero PII filtering. That’s fine for prototyping. It’s not fine for production. Set a budget cap on every workspace as the first action. The other three guardrail categories you can configure as you scale.

    See also: The Multi-Model AI Roundtable: A Three-Round Methodology for Better Decisions · What We Learned Querying 54 LLMs About Themselves (For $1.99 on OpenRouter)

  • Claude Code managed-settings.json: The Org-Wide Policy File Most Teams Skip

    Claude Code managed-settings.json: The Org-Wide Policy File Most Teams Skip

    Last week I wrote about the three-file split every team should set up in their repo: CLAUDE.md, .claude/settings.json, and .claude/settings.local.json. That gets a team to a sane shared baseline. It does not stop a single engineer with admin rights on their laptop from disabling every guardrail you wrote.

    If you are deploying Claude Code to more than a handful of engineers — anyone past Series B, anyone regulated, anyone whose CISO has asked a single pointed question about AI tooling — repo-level settings are insufficient. The control you want is managed-settings.json, and most teams I talk to either do not know it exists or have not deployed it.

    Where managed-settings.json Actually Lives

    Claude Code reads settings in a strict precedence order. Managed settings sit at the top and cannot be overridden by anything a user does in their repo, their home directory, or their environment. The file location depends on the OS:

    • macOS: /Library/Application Support/ClaudeCode/managed-settings.json
    • Linux / WSL: /etc/claude-code/managed-settings.json
    • Windows: C:\Program Files\ClaudeCode\managed-settings.json

    You push the file via whatever you already use to manage developer machines. On macOS that is MDM — Jamf, Kandji, Mosyle. On Windows it is Group Policy Preferences. On Linux fleets, your config management tool of choice — Ansible, Chef, whatever survived your last platform team rewrite. The file does not need to be created by Claude Code itself. It just needs to be present at the path above, owned and writable only by an admin account, and readable by the user running claude.

    The One Rule That Earns Its Keep: permissions.deny

    Of every field in managed-settings.json, the one that pays for the entire deployment effort is permissions.deny. Deny rules at the managed-settings tier take effect regardless of any allow or ask rules at lower scopes. A user cannot grant themselves permission to do something an admin has denied — not in their project settings, not in their personal settings, not via a one-time CLI flag.

    Concretely, here is a minimum-viable managed file for a team that wants to stop the obvious foot-guns:

    {
      "permissions": {
        "deny": [
          "Bash(curl:*)",
          "Bash(wget:*)",
          "Bash(rm -rf /*)",
          "Read(./.env)",
          "Read(./.env.*)",
          "Read(./**/credentials*)",
          "Read(./**/*secret*)"
        ]
      }
    }

    That blocks Claude from curl-ing arbitrary URLs (the most common vector for accidental data exfiltration in agentic loops), reading anything in an .env file, and deleting filesystem roots in a Bash one-liner gone wrong. It does not stop legitimate work. It stops the long tail of “I didn’t realize it would do that.”

    The Drop-In Directory Is the Underrated Piece

    The single-file model breaks the moment you have more than one team contributing policy. Security wants curl blocked, platform wants kubectl delete blocked, the data team wants reads against the /data/prod/ mount blocked. Funneling all three through a single admin-owned file becomes a coordination tax.

    Claude Code supports a drop-in directory at managed-settings.d/ in the same parent directory as managed-settings.json. Files in that directory are merged alphabetically — same convention as systemd and sudoers.d. Layout looks like this:

    /Library/Application Support/ClaudeCode/
    ├── managed-settings.json          # base policy
    └── managed-settings.d/
        ├── 10-security.json           # security team owns
        ├── 20-platform.json           # platform team owns
        └── 30-data.json               # data team owns

    Each team owns one file. They push their fragment through their own MDM channel without touching the others. Merge order is alphabetical, so the number prefix matters — later files override earlier ones for any overlapping keys, but permissions.deny rules always accumulate. Nothing a later file does can unblock something an earlier file denied.

    What Belongs in Managed Settings — and What Does Not

    Managed settings is a heavy hammer. Use it for things that must not be overridable. Everything else belongs in the repo’s .claude/settings.json, where engineers can iterate without filing a ticket.

    Belongs in managed:

    • Deny rules for credentials, network egress, destructive shell operations
    • Telemetry / opt-out flags if your contract with Anthropic requires training data opt-out
    • Default model if you have a real reason to pin — most teams should let repos choose
    • Audit log paths if you are forwarding to a SIEM

    Does not belong in managed:

    • Project-specific subagents or hooks (these live in the repo)
    • CLAUDE.md content (repo)
    • Allow rules — these are better as defaults at the repo scope, where engineers can adjust per-task

    Verifying the Policy Is Actually Active

    Pushing a config file is not the same as enforcing one. After deployment, run claude config list on a test machine and confirm the managed entries show up. Then attempt something the deny rule blocks — try a curl command, ask Claude to read an .env. The denial should be immediate and unambiguous, not a quiet skip. If a user can override it from their repo settings, the file is not at the right path or not readable by the user account running claude.

    Model Selection at the Org Level

    If you do pin a default model in managed settings — and I would argue most teams should not — read the model docs at docs.anthropic.com/en/docs/about-claude/models before writing the version string. Model identifiers change. As of this writing the workhorse is claude-sonnet-4-6, the flagship is claude-opus-4-7, and the fast option is claude-haiku-4-5-20251001. Hardcoding a model string in a managed file that nobody touches for six months is how you end up running last year’s model in production.

    Where This Approach Loses

    Managed settings cover the local Claude Code process. They do not cover the Anthropic Console, the Claude web app, or any MCP server an engineer connects to manually. If your threat model includes data leaving via the web app, managed settings on developer laptops are not the answer — the Enterprise plan’s org-level controls and SSO are. The two layers compose. Neither replaces the other.

    Managed settings also do nothing about an engineer who runs Claude Code on a personal machine outside MDM scope. That is a device management problem, not a Claude Code problem, and the fix is the same as it has always been: do not let unmanaged machines touch production code.

    The 30-Minute Rollout

    1. Pick one platform — start with whichever fleet is largest, usually macOS
    2. Write the minimum-viable managed-settings.json above
    3. Push it to one test machine via MDM, verify with claude config list
    4. Try three things the deny rules should block; confirm all three are blocked
    5. Roll to the rest of the fleet
    6. Set up the managed-settings.d/ directory so other teams can layer their own fragments without coordination

    The whole exercise is half a day of work for a platform engineer who already knows your MDM. The alternative is hoping every engineer reads the same Notion page about which commands not to run. Hope is not a security control.

  • How to Install and Deploy Claude Code in Production: The Complete Team Guide (May 2026)

    How to Install and Deploy Claude Code in Production: The Complete Team Guide (May 2026)

    Last refreshed: May 15, 2026

    Claude Code production deployment - install paths, CI integration, and team-scale cost controls
    Installing Claude Code is the easy part. Deploying it across a team in production is the part most guides skip.

    Most of the published guidance on installing Claude Code stops at “run npm install -g and you’re done.” That’s enough for a developer playing on a laptop. It is not enough for a team that wants to run Claude Code in production — in CI, in shared infrastructure, behind a firewall, with cost controls, and with the new Agent SDK billing model that takes effect June 15, 2026.

    This article is the production deployment guide. Triple-sourced against Anthropic’s own Claude Code documentation, the github.com/anthropics/claude-code-action repo, and Anthropic’s announced June 15 billing model. Verified May 15, 2026.

    The three install paths and which to pick

    Per Anthropic’s official Claude Code docs, there are three supported ways to install Claude Code. They produce the same underlying binary but make sense in different operational contexts.

    1. Standalone installer. A native installer for macOS, Windows, and Linux that drops the Claude Code binary in a system path. This is the cleanest install for individual developers — no Node.js required, no npm dependency, predictable upgrade behavior. Use this on workstations where the operator owns the machine.

    2. npm global package. npm install -g @anthropic-ai/claude-code. Requires Node.js 18 or later. Pulls the same native binary as the standalone installer through a per-platform optional dependency, then a postinstall step links it into place. Use this when you already manage developer tools through npm and want one less install path to track. Supported platforms: darwin-arm64, darwin-x64, linux-x64, linux-arm64, linux-x64-musl, linux-arm64-musl, win32-x64, win32-arm64.

    3. Desktop app. A desktop-class application distributed via .dmg on macOS and MSIX/.exe on Windows. This is the path most teams will deploy to non-developer staff, and it integrates with enterprise device management tools like Jamf, Kandji, and standard Windows MSIX deployment.

    If you are deploying across a team larger than a handful of developers, mix-and-match: standalone or npm for engineering workstations, desktop for everyone else.

    The npm install gotchas worth knowing before you ship

    Two things in Anthropic’s official docs are worth flagging because they will save you from a whole class of bug reports later:

    Don’t use sudo. Anthropic’s setup documentation explicitly warns against sudo npm install -g @anthropic-ai/claude-code. It can lead to permission issues and security risks. If you need a global install on a machine where your user can’t write to the npm prefix, fix the npm prefix first (point it at a user-writable directory) rather than escalating with sudo.

    Don’t use npm update for upgrades. The right command per Anthropic’s docs is npm install -g @anthropic-ai/claude-code@latest. npm update -g respects the original semver range and may not move you to the newest release. This trips up CI pipelines that try to keep Claude Code current via update; they will sit on a stale version forever.

    Production deployment considerations

    The single most important piece of context for a production Claude Code deployment in 2026: the billing model changes on June 15, 2026.

    Before June 15, Claude Code interactive sessions and claude -p non-interactive runs both draw from your normal subscription usage limits. Starting June 15, interactive Claude Code keeps using subscription limits as before, but claude -p and direct Agent SDK usage move to a separate per-user monthly Agent SDK credit pool ($20 Pro, $100 Max 5x, $200 Max 20x, $20-$100 Team, up to $200 Enterprise).

    For teams running Claude Code in CI, in cron jobs, in shell scripts, in GitHub Actions workflows — anywhere the trigger is automated rather than a human — this changes the economics. Plan capacity against the new credit pool, not the legacy shared subscription pool. Full breakdown in our Agent SDK Dual-Bucket Billing article.

    Three other production considerations:

    Network configuration. Behind a corporate firewall, you’ll need to allowlist Anthropic’s API endpoints, configure proxy settings, and potentially route through an LLM gateway. Anthropic’s network configuration documentation covers the specifics.

    Enterprise device deployment. Per Anthropic’s official docs, the desktop app distributes through standard enterprise tools — Jamf and Kandji on macOS via the .dmg installer, MSIX or .exe on Windows. If your IT team already has a deployment workflow for similar developer tools, Claude Code drops into it without anything special.

    API key management. If your team uses Claude Developer Platform API keys instead of (or alongside) subscription auth, manage them like any other production secret — vault them, rotate them, scope them per environment, never check them into source control. This becomes more important after June 15 because API key usage is the recommended path for sustained shared automation, and unintended sprawl gets expensive.

    Claude Code GitHub Actions: the team multiplier

    The fastest way to get team-level value from Claude Code is the official GitHub Actions integration. From Anthropic’s documentation and the public github.com/anthropics/claude-code-action repository:

    The setup command. The cleanest install is to run /install-github-app from inside Claude Code in your terminal. It walks you through installing the GitHub App, configuring the required secrets, and wiring the workflow file. Manual setup also works — copy the workflow YAML from Anthropic’s docs and add the ANTHROPIC_API_KEY secret to your repository settings — but the install command saves the assembly time.

    The interaction model. Once installed, mentioning @claude in a pull request comment or an issue triggers Claude Code to act on the context. Claude can analyze the diff, create new PRs, implement features described in an issue, fix reported bugs, and respond to follow-up comments — all while adhering to whatever conventions you’ve documented in your repository’s CLAUDE.md file.

    Three use cases worth separating clearly.

    • Automated code review. Claude Code reads the diff on every pull request and posts inline comments flagging potential issues, suggesting improvements, or checking for convention violations. Highest signal-to-noise when path-filtered to relevant code only.
    • Issue-to-PR automation. Tag @claude on a well-described issue and Claude Code opens a PR implementing it. Best for small, well-scoped changes; less useful for architectural work.
    • On-demand assistance. Reviewers tag @claude mid-PR to ask questions, request explanations, or get a second opinion before merging. The most defensible use case because it keeps a human in the decision loop.

    Pick the use case that matches your team’s actual bottleneck. Running all three at once on every PR is the fastest way to burn through your usage budget without proportionate value.

    Cost expectations at team scale

    Independent reports as of May 2026 put Claude Code GitHub Actions PR-review costs at roughly $15-25 per month for a team of 3-5 developers doing 10-15 PRs per week, billed against a Claude Developer Platform API key at Sonnet rates. That figure should be treated as directional — your actual cost depends on PR size, how many tools you’ve configured, model selection, and how aggressive your path-filtering is.

    Two cost controls that materially change the math:

    • Path filters. Trigger Claude Code only on file changes that actually need review. Skipping documentation, generated files, and lockfile-only PRs cuts the bill substantially.
    • Concurrency limits. GitHub Actions concurrency settings prevent Claude Code from running multiple instances against the same branch at once. Without this, force-pushes and rapid-fire updates can stack runs.

    If you are running Claude Code on every PR across an active team, you will hit Anthropic API rate limits. The mitigation is path filters, concurrency limits, and batching — none of which are speculative; they are documented patterns.

    The CLAUDE.md file is not optional

    Whatever your install path and whatever your use case, the single piece of project context that has the largest effect on Claude Code’s output is the CLAUDE.md file at the root of your repository. This is where you tell Claude Code what your project is, what conventions to follow, what tools are available, what to avoid, and what success looks like.

    If you skip it, Claude Code is reasoning from the files alone — useful but generic. If you write it, Claude Code is reasoning with your team’s context and your specific codebase rules. The difference shows up in the first ten minutes of use.

    A practical CLAUDE.md for a production team usually includes: the project’s purpose and stack, naming conventions and folder structure, testing requirements, lint and format rules, deployment considerations, what kinds of changes need human review, and explicit prohibitions (“never commit migrations directly to main”, “always update X when you change Y”). Keep it concise — verbose CLAUDE.md files inflate every per-turn token cost across the team.

    What to actually do this week

    1. Pick your install path per role (standalone or npm for developers, desktop for everyone else).
    2. Install Claude Code on one workstation and run through the quickstart end-to-end before rolling to the team.
    3. Write a real CLAUDE.md for your primary repository before anyone uses Claude Code on it. Even a 100-line version is far better than nothing.
    4. If you’re running anything automated, read the Agent SDK billing change before June 15.
    5. If you want team-level value, install the GitHub Actions integration — but pick one use case (code review, issue-to-PR, or on-demand help), not all three at once.
    6. Set path filters and concurrency limits in your workflow before you put Claude Code on every PR.

    Frequently Asked Questions

    What’s the difference between the npm install and the standalone installer?

    None functionally — both install the same native binary. The npm path is convenient if you already manage developer tools through npm. The standalone installer is cleaner if you don’t want a Node.js dependency. Both upgrade through their own mechanism.

    Why does Anthropic say not to use sudo with npm install?

    Per Anthropic’s official setup documentation, sudo with global npm installs can create permission issues and security risks. The recommended fix is to configure your npm prefix to a user-writable directory, then install without elevated privileges.

    How do I upgrade Claude Code installed via npm?

    Run npm install -g @anthropic-ai/claude-code@latest. Don’t use npm update -g — it respects the original semver range and may not move you to the latest release. This is documented in Anthropic’s setup guide.

    Does Claude Code work in CI/CD pipelines?

    Yes. The official GitHub Actions integration is the recommended path for GitHub-based workflows. For other CI systems (GitLab, CircleCI, Jenkins), the underlying tool is the Claude Agent SDK plus claude -p. Both move to the new Agent SDK monthly credit pool on June 15, 2026.

    How much does Claude Code GitHub Actions cost for a team?

    Independent reports as of May 2026 estimate $15-25/month for a 3-5 developer team running PR review on 10-15 PRs/week at Sonnet rates with a Claude Developer Platform API key. Actual cost varies with PR size, tool configuration, model selection, and path filtering aggressiveness.

    What’s the single biggest mistake teams make installing Claude Code?

    Skipping the CLAUDE.md file. Without it, Claude Code reasons generically against your codebase. With even a basic CLAUDE.md describing your conventions and constraints, output quality improves substantially across every interaction. It is the highest-leverage 30-minute setup task.

    Related Reading

    How we sourced this

    Sources reviewed May 15, 2026:

    • Anthropic Claude Code documentation: Set up Claude Code and Advanced setup at code.claude.com (primary source for install paths, npm gotchas, enterprise deployment patterns)
    • Anthropic Claude Code GitHub Actions documentation at code.claude.com/docs/en/github-actions (primary source for the GitHub Actions integration setup and use cases)
    • github.com/anthropics/claude-code-action public repository (primary source for the action’s interaction model)
    • Anthropic Help Center: Use the Claude Agent SDK with your Claude plan (primary source for the June 15, 2026 billing change)
    • Independent cost analyses (KissAPI, OpenHelm, Steve Kinney) for the team-scale cost estimates — Tier 2 confirming sources

    Cost figures and version specifics in this article are accurate as of May 15, 2026. Anthropic ships Claude Code updates frequently; the install paths and CLI commands are stable, but pricing and rate limits are the most likely figures to need re-verification.

  • LLMs.txt in 2026: The 4-Element Spec, The Robots.txt Pairing, and How to Verify Crawlers Are Reading It

    LLMs.txt in 2026: The 4-Element Spec, The Robots.txt Pairing, and How to Verify Crawlers Are Reading It

    If you publish an llms.txt file this week, no major model is going to fetch it tonight. That is the honest 2026 read on the spec — and yet the file is still worth shipping for narrow, specific reasons. This guide covers the 4-element specification published at llmstxt.org, the robots.txt pairing that actually controls AI crawler behavior right now, and a server-log filter you can run to verify whether anyone is reading the file you just shipped.

    What llms.txt actually is (and what it isn’t)

    llms.txt is a Markdown file served at the site root — /llms.txt — proposed by Jeremy Howard of Answer.AI on September 3, 2024. The spec at llmstxt.org defines four elements: a required H1 with the project or site name; a blockquote summary; zero or more Markdown content sections (no headings); and zero or more H2-delimited file-list sections containing annotated Markdown links to deeper content. That is the entire specification. There is no header convention, no schema requirement, no robots-style allow/deny syntax.

    What llms.txt is not: it is not a substitute for robots.txt, it is not an access-control mechanism, and as of May 2026 it is not consumed at inference time by ChatGPT, Claude, Gemini, Perplexity, or Copilot in any documented production system. Server-log audits across multiple independent practitioners show GPTBot, ClaudeBot, and Google-Extended do not request /llms.txt in meaningful volume during routine crawls.

    The realistic 2026 use case is developer tooling. AI coding assistants and IDE agents — Cursor, GitHub Copilot, Claude Code, and similar tools — retrieve docs in real time, and a curated llms.txt cuts token waste by pointing them at canonical Markdown sources instead of HTML-rendered pages bloated with nav and tracking. Companies like Anthropic, Stripe, Cursor, Cloudflare, Vercel, Mintlify, Supabase, and LangGraph ship llms.txt for that reason.

    The 4-element template — a working example

    Here is a real, valid llms.txt for a hypothetical SaaS docs site. Copy this structure, change the project name, and you have a shippable file in under 30 minutes:

    # Acme Analytics
    
    > Acme Analytics is a self-hosted product analytics platform for SaaS teams. This file points AI assistants and IDE agents at canonical Markdown documentation, not the rendered HTML.
    
    Authoritative Markdown sources for product, API, and SDK documentation. Use the `.md` variant of any docs page (append `.md` to the URL) for a clean, agent-friendly version.
    
    ## Getting Started
    
    - [Quickstart](https://acme.example/docs/quickstart.md): 10-minute setup, install through first event.
    - [Concepts](https://acme.example/docs/concepts.md): events, properties, identities, sessions — definitions and examples.
    
    ## API Reference
    
    - [REST API Reference](https://acme.example/docs/api/rest.md): every endpoint, request/response schema, rate limits.
    - [Webhook Reference](https://acme.example/docs/api/webhooks.md): payload contracts and retry behavior.
    
    ## SDKs
    
    - [JavaScript SDK](https://acme.example/docs/sdk/js.md): browser and Node, including server-side rendering notes.
    - [Python SDK](https://acme.example/docs/sdk/python.md): server-side ingestion patterns.
    
    ## Optional
    
    - [Changelog](https://acme.example/docs/changelog.md): version history, breaking changes flagged inline.
    

    Two practitioner notes. First, the spec uses an “Optional” H2 as a soft signal — links under that heading can be skipped by aggressive token budgets. Second, the file is most useful when every linked URL has a parallel .md Markdown version. If your site is pure HTML, llms.txt without paired Markdown does little.

    The robots.txt pairing — this is what actually controls AI bots today

    The lever that meaningfully controls AI crawler behavior in 2026 is robots.txt with user-agent–specific rules. Anthropic publishes official documentation for three bots — ClaudeBot for training, Claude-User for user-initiated fetches, and Claude-SearchBot for search indexing — and confirms all three honor robots.txt. OpenAI runs GPTBot (training) and OAI-SearchBot (live ChatGPT search). Google’s AI training opt-out is the Google-Extended user-agent. Perplexity uses PerplexityBot.

    The two-bucket pattern most practitioner sites should ship: block training-only crawlers, allow search and user-initiated retrieval so your content can still be cited in answers.

    # Allow AI search and user-fetch traffic (citations, attribution)
    User-agent: Claude-SearchBot
    Allow: /
    
    User-agent: Claude-User
    Allow: /
    
    User-agent: OAI-SearchBot
    Allow: /
    
    User-agent: PerplexityBot
    Allow: /
    
    # Block training-only crawlers
    User-agent: ClaudeBot
    Disallow: /
    
    User-agent: GPTBot
    Disallow: /
    
    User-agent: Google-Extended
    Disallow: /
    
    # Standard search crawler — leave open
    User-agent: Googlebot
    Allow: /
    
    Sitemap: https://example.com/sitemap.xml
    

    One operational caveat: robots.txt is policy, not enforcement. Anthropic, OpenAI, and Google have all publicly committed their named bots to compliance, but unnamed scrapers and residential-IP harvesters routinely ignore it. For sites with sensitive content, pair robots.txt with WAF or Cloudflare bot-management rules at the edge.

    Structured data still does more heavy lifting than llms.txt

    If your goal is AI citation rather than IDE-agent retrieval, structured data on the page itself moves the needle more than llms.txt. The minimum stack for any article you want cited: Article schema with named author and publisher, FAQPage schema on any post that answers a discrete question, and speakable markup on the answer paragraphs. These get parsed during normal HTML fetches by every major AI crawler — no separate file required.

    How to verify your llms.txt is actually being read

    Ship the file, then run this server-log filter weekly for 30 days. On any standard access-log format (nginx, Apache, or a Cloudflare log push), grep for requests to /llms.txt and break them down by user-agent:

    grep "GET /llms.txt" /var/log/nginx/access.log \
      | awk -F\" '{print $6}' \
      | sort | uniq -c | sort -rn
    

    What you will almost certainly see in May 2026: a steady trickle of human curl requests, the occasional IDE agent fetch tagged with a Cursor or VS Code user-agent, and effectively zero hits from GPTBot, ClaudeBot, or Google-Extended. That null result is itself the measurement — it tells you llms.txt is a developer-experience asset right now, not an AI-citation asset, and your investment should match that reality.

    The recommended 2026 rollout

    For most sites, the right sequence is: ship the robots.txt user-agent rules above first, because those are enforceable today and shape every AI crawler interaction. Add structured data to every article that competes for AI citation. Then publish llms.txt — under 30 minutes of work — for the IDE-agent and dev-tooling upside, with no expectation of immediate search lift. When OpenAI, Anthropic, or Google publicly confirm production llms.txt consumption, you are already in position.

  • Claude MCP in 2026: What Actually Changed and How to Configure It Without Wasting Tokens

    Claude MCP in 2026: What Actually Changed and How to Configure It Without Wasting Tokens

    Last refreshed: May 15, 2026

    If you set up Claude MCP six months ago and have not touched the config since, three things have changed underneath you: the recommended transport, how tools are loaded into context, and how teams share server configs. None of these are cosmetic. If you ignore them, you are leaving tokens, money, and stability on the table.

    This is the working Claude MCP setup I use in May 2026 — what the claude mcp add command actually does, which scope to pick, what the deprecation of SSE means in practice, and where Claude Code still falls short.

    The three-scope mental model

    Every MCP server you wire into Claude Code lives at exactly one of three scopes. Get this wrong and you will either leak credentials into git or wonder why your teammate cannot use the same database the AI just queried.

    • Local (default): the server is available only to you, only inside the current project. Config is written into your project’s entry inside ~/.claude.json. Good for project-specific servers like a dev database or a Sentry project key you do not want other repos to inherit.
    • User: the server is available to you across every project on your machine. Also stored in ~/.claude.json. This is where GitHub, search providers, and personal productivity servers belong.
    • Project: the server is written to a .mcp.json file at the repo root and shared with the whole team via git. Claude Code prompts for approval the first time a teammate opens the project — by design, because anyone who can push to the repo can wire a new server into your environment.

    When the same server is defined in more than one scope, Claude Code resolves it in this order: local beats project beats user beats plugin-provided. This is the part that bites people the most. If you have a “github” entry at user scope and someone adds a different “github” entry at project scope in .mcp.json, the project definition wins for that repo. Run claude mcp list when something behaves strangely.

    The commands you actually need

    The CLI is more useful than the docs make it look. Three commands cover ~90% of real setup work:

    # Add a remote HTTP MCP server at user scope (available everywhere)
    claude mcp add --transport http hubspot --scope user https://mcp.hubspot.com/anthropic
    
    # Add a local stdio server scoped only to this project
    claude mcp add my-db -s local -- node ./scripts/db-mcp.js
    
    # Share a server with your team via the repo's .mcp.json
    claude mcp add my-server -s project -- node server.js

    The short flag is -s, the long is --scope. The -- separator is required for stdio servers because everything after it is treated as the literal command to spawn. Forget it and Claude Code will try to interpret your Node arguments as its own flags.

    SSE is dead. Use Streamable HTTP.

    If your MCP server documentation still tells you to use the sse transport, the documentation is stale. The MCP spec dated 2025-03-26 introduced Streamable HTTP and simultaneously deprecated HTTP+SSE. Through 2026, vendor after vendor has set hard cutoff dates — Atlassian’s Rovo MCP server keeps SSE around until June 30, 2026 and then drops it; Keboola pulled SSE on April 1; Cumulocity’s AI Agent Manager flipped to Streamable HTTP on May 8.

    Why this matters beyond a name change: SSE required Claude Code to hold a persistent connection to a single server replica, which broke horizontal scaling and made every transient network blip a reconnection drama. Streamable HTTP is stateless. Multiple replicas behind a load balancer just work. If you have flaky MCP connections in production, the first thing to check is whether the server is still on SSE.

    For new setups, use --transport http. The older --transport sse still functions but is on the deprecation path.

    Tool Search is the feature you should actually care about

    The single biggest change in how Claude Code uses MCP in 2026 is lazy tool loading via Tool Search. Older MCP clients dumped every tool schema from every connected server into the model’s context window at the start of every conversation. With ten servers wired up that could easily be 20,000+ tokens of overhead before you typed a single character.

    Tool Search inverts this. Claude Code keeps only the server names and short descriptions resident. When a tool is actually needed, it fetches that tool’s full schema on demand. Anthropic’s own documentation says this reduces tool-definition context usage by roughly 95% versus eager-loading clients. In practice that means you can run a serious MCP fleet — GitHub, Sentry, a database, a search provider, your internal API — without quietly burning through your context budget. The Sonnet 4.6 and Opus 4.7 1M-token context window does not save you here, because anything you let crowd the prompt is also being re-read on every turn.

    Companion feature: list_changed notifications. An MCP server can now tell Claude Code “my tool list changed” and Claude Code refreshes capabilities without a disconnect-reconnect dance. If you build your own server, emit this when you swap tool definitions and you save users a restart.

    What it still gets wrong

    Honest take: claude mcp list still does not surface scope information for every entry in a useful way — there is an open issue on the anthropics/claude-code repo asking for it (#8288 if you want to track). Project-scoped servers from .mcp.json have a separate history of not appearing in the list output (#5963) depending on how you opened the project. If you cannot find a server, check both ~/.claude.json and ./.mcp.json directly.

    The other rough edge is the project-approval prompt. The first time you open a repo with a new .mcp.json, Claude Code asks you to approve each project-scoped server. That is the right security default. It is also infuriating in CI or any non-interactive shell, where the prompt blocks the session. The current workaround is to bake the servers in at user scope on build agents so the project-scope approval never fires in CI. A cleaner non-interactive approval flow is the single most-requested fix I see in real teams.

    The setup I would run on a new machine today

    User-scope: GitHub, a code search server, and a single notes/Notion server. Project-scope in each repo’s .mcp.json: whatever database the project owns and whatever observability backend it reports to. Local-scope: anything experimental I am evaluating but do not want my team or my other repos to inherit.

    Pin --transport http on everything remote. Skip Desktop Extensions (.dxt) for anything you want versioned with the codebase — they are a Claude Desktop convenience, not a Claude Code primitive, and they hide the config from your team. Run claude mcp list when something is off and read .mcp.json directly when list is unhelpful.

    That is the whole working model. The pieces that matter — three scopes, Streamable HTTP, Tool Search — fit on a single screen. The pieces that have not caught up yet — list output, non-interactive approvals — are visible in the issue tracker and will move.