ES · Leer en español Explore for free

Recipe · Intermediate · 15 min

MCP in Claude Code: connect Playwright, GitHub and your database

Add MCP servers to Claude Code with claude mcp add, share them in .mcp.json, control permissions and context, and avoid leaked secrets and injection.

Tested with Claude Code 2.1.316 · reviewed

The problem

Claude Code reads and edits your code, but it can't see your site in a browser, your GitHub issues or your database tables. You end up copying and pasting screenshots, errors and query results. MCP (Model Context Protocol) connects Claude Code to those real tools, but a careless setup fills your context, leaks tokens into the repository or opens the door to malicious instructions.

The solution

1. Understand the two kinds of server

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

# http
claude mcp add --transport http <name> <url>

2. Pick the scope

ScopeLoads inSharedStored in
local (default)This project onlyNo~/.claude.json
projectThis project onlyYes, via git.mcp.json at the root
userAll your projectsNo~/.claude.json

Rule of thumb: project for what the whole team needs (no secrets inside), local for anything holding your credentials or only you use, user for personal tools you want everywhere. If a server exists in several scopes, local wins, then project, then user.

3. Playwright MCP: let Claude test your site in a browser

Microsoft's official server (package @playwright/mcp, requires Node.js 18 or newer). From your project root:

claude mcp add --scope project playwright -- npx @playwright/mcp@latest --headless --isolated

--headless runs the browser without a window and --isolated keeps the profile in memory only (no cookies left on disk). This creates or updates .mcp.json:

{
  "mcpServers": {
    "playwright": {
      "type": "stdio",
      "command": "npx",
      "args": [
        "@playwright/mcp@latest",
        "--headless",
        "--isolated"
      ],
      "env": {}
    }
  }
}

Then ask things like: "Open http://localhost:8000, take a snapshot and tell me what errors show up in the console." It will use tools such as browser_navigate, browser_snapshot and browser_console_messages.

4. GitHub MCP in read-only mode, with the token kept out of the repo

GitHub's official server is remote (https://api.githubcopilot.com/mcp/). Adding /readonly to the end of the URL leaves only the read tools. In .mcp.json you can use ${VARIABLE}, so the token is never written to the file:

claude mcp add-json --scope project github '{"type":"http","url":"https://api.githubcopilot.com/mcp/readonly","headers":{"Authorization":"Bearer ${GITHUB_PAT}"}}'

Each person exports their own token before starting Claude Code (create a fine-grained token with the minimum permissions):

export GITHUB_PAT="your_token_here"
claude

Watch out: ${VARIABLE} expansion works in .mcp.json. With --scope local or user the text is stored as-is in ~/.claude.json and isn't expanded (we checked: the server answers "Authorization header is badly formatted").

5. A database with DBHub (try the sample data first)

DBHub (@bytebase/dbhub) talks to PostgreSQL, MySQL, SQL Server, MariaDB, Oracle and SQLite. To try it without touching your data, use its sample database:

claude mcp add --scope local db -- npx -y @bytebase/dbhub@latest --transport stdio --demo

For your real database, pass the connection string in the DSN variable and connect with a read-only database user. Use local scope, because the password is stored in your ~/.claude.json:

claude mcp add --scope local --env DSN="postgres://reader:password@localhost:5432/myapp" --transport stdio db \
  -- npx -y @bytebase/dbhub@latest --transport stdio

DBHub also supports readonly = true and max_rows for its execute_sql tool in its TOML file (docs), but its own docs warn that this doesn't replace a low-privilege user.

6. Check status and authenticate with /mcp

Inside Claude Code type /mcp: you'll see each server and its status, you can sign in with OAuth to remote servers that require it, and you can disable the ones you aren't using without removing them. From the terminal:

claude mcp list                 # all servers and their health
claude mcp get playwright       # details for one
claude mcp remove playwright -s project

The first time you open claude in a project with .mcp.json, it asks you to approve those servers. To be asked again: claude mcp reset-project-choices.

7. Permissions: approve only what you trust

MCP tools are named mcp__<server>__<tool>. In .claude/settings.json:

{
  "permissions": {
    "allow": [
      "mcp__playwright__browser_navigate",
      "mcp__playwright__browser_snapshot",
      "mcp__github__get_*"
    ],
    "deny": [
      "mcp__playwright__browser_run_code_unsafe"
    ]
  }
}

mcp__github__* covers every tool from the github server, and mcp__github__get_* only those starting with get_. A wildcard without a server, such as "mcp__*", approves nothing in allow (it does work in deny to block all MCP).

8. Watch your context

By default Claude Code uses tool search: at startup it loads only tool names and each server's instructions, and fetches the full definition when needed. Even so, each server adds names, instructions and long responses: Claude Code warns when an MCP tool returns more than 10,000 tokens and cuts off at 25,000 by default (MAX_MCP_OUTPUT_TOKENS). Disable in /mcp whatever you don't use for the current task and check usage with /context.

Check it

After step 3 (and step 4, without exporting GITHUB_PAT), at the project root:

claude mcp list

Real output with Claude Code 2.1.316 (trimmed to our servers):

Checking MCP server health…

playwright: npx @playwright/mcp@latest --headless --isolated - ⏸ Pending approval (run `claude` to approve)
github: https://api.githubcopilot.com/mcp/readonly (HTTP) - ⏸ Pending approval (run `claude` to approve)
[Contains warnings] Project config (shared via .mcp.json)
 └ [Warning] [github] mcpServers.github: Missing environment variables: GITHUB_PAT
claude mcp get playwright
playwright:
  Scope: Project config (shared via .mcp.json)
  Status: ⏸ Pending approval (run `claude` to approve)
  Type: stdio
  Command: npx
  Args: @playwright/mcp@latest --headless --isolated
  Environment:

To remove this server, run: claude mcp remove playwright -s project

"Pending approval" is expected: open claude, approve the project servers, and /mcp should then show them connected. The GITHUB_PAT warning goes away once you export the variable.

Why it works

Claude Code acts as an MCP client: it starts each stdio server as a child process (or connects over HTTP), asks for its tool list and offers those tools to Claude with the mcp__<server>__ prefix. Every call goes through the same permission system as Bash or Edit. .mcp.json is a normal repository file, which is why it's good for sharing configuration and why it must never hold secrets. More in the official MCP docs for Claude Code and the permissions docs.

Common mistakes

FAQ

Is it safe to connect any MCP server?

No. Only install servers you trust: a stdio server runs on your machine with your permissions. Also, servers that read external content (web pages, issues, database rows) can bring in prompt injection: text that tries to make Claude do something you didn't ask for. That's why read-only GitHub, low-privilege database users and reviewing every action before approving it are worth it.

Where do I put tokens and passwords?

Never inside .mcp.json. Write ${VARIABLE} in the file and set the variable in your terminal, or use local scope, which stores the config in your ~/.claude.json and never gets pushed to the repository.

What's the difference between local and user?

Both are stored in ~/.claude.json and aren't shared. local loads only in the project where you added it; user loads in all your projects.

Does Playwright MCP isolate dangerous sites?

No. Its README says it's not a security boundary, and browser_run_code_unsafe runs arbitrary JavaScript in the server process. Use it to test your own pages.

How do I turn a server off without removing it?

In /mcp, select it and disable it. Claude Code stores that choice per project in ~/.claude.json.

All recipes