# Claude Code MCP: add og:image to a blog and take screenshots from the terminal

> One claude mcp add command connects the image API to Claude Code. Scopes, keeping the key out of git, and a worked example: og:image for every blog post.

Published 2026-11-04 · https://shareglint.com/en/mcp/claude-code

Claude Code can render Open Graph images, take screenshots of web pages and edit your site so every page gets an `og:image` once you add Shareglint as a remote MCP server with one command: `claude mcp add --transport http shareglint https://shareglint.com/mcp --header "Authorization: Bearer $OG_API_KEY"`. The tools (`render_image`, `get_image`, `list_templates`, `get_template`, `create_signed_url`, `get_usage`, `generate_template`, `take_screenshot`, `auto_og_url`, `create_batch`, `get_batch`) act on your account and its quota — 100 renders a month on the Free plan.

The [overview guide](https://shareglint.com/en/guides/og-images-with-ai-assistants-mcp) covers MCP in general and the other clients. This page is Claude Code only: scopes, keys, a worked example and the problems you are likely to hit.

## What Claude Code can do with the tools

Claude Code reads and edits your repository and runs commands, so it can use a tool's result straight away:

- **Add og:image to a site.** It calls `create_signed_url` once to learn the URL format, writes a helper in your language and adds the tag to your layout.
- **Backfill images for an archive.** It reads your posts, builds rows and calls `create_batch`, then `get_batch` to collect each post's image URL and write it into front matter.
- **Check a card while you work.** "Render the card for this draft with blog-og" is one `render_image` call; open the URL it prints.
- **Screenshots for docs.** `take_screenshot` with `selector` for one element or `device: "iphone-15"` for a phone view, then `curl` the file into `docs/img/`.
- **Watch the budget.** `get_usage` before a big batch.

## Add the server

Claude Code's [MCP documentation](https://code.claude.com/docs/en/mcp) describes `claude mcp add` for remote HTTP servers. Create a key in the Shareglint dashboard (a separate one for the agent, so you can revoke it alone), then:

```bash
export OG_API_KEY="sk_live_…"

claude mcp add --transport http shareglint https://shareglint.com/mcp \
  --header "Authorization: Bearer $OG_API_KEY"
```

Your shell expands `$OG_API_KEY` before Claude Code sees it, so the **value** is stored in Claude Code's config (`~/.claude.json`), outside the repository. That is fine for local and user scope. Check the result with `claude mcp get shareglint`, list all servers with `claude mcp list`, and remove it with `claude mcp remove shareglint`. Inside a session, `/mcp` shows whether it is connected.

### Pick a scope

| Scope | Flag | Stored in | Who gets it |
|---|---|---|---|
| local (default) | `--scope local` | `~/.claude.json`, under this project | you, in this project |
| user | `--scope user` | `~/.claude.json` | you, in every project |
| project | `--scope project` | `.mcp.json` in the repository | everyone who clones it |

For a team, use project scope **with a variable, not the value**. Write `.mcp.json` by hand so the shell does not expand anything:

```json
{
  "mcpServers": {
    "shareglint": {
      "type": "http",
      "url": "https://shareglint.com/mcp",
      "headers": { "Authorization": "Bearer ${OG_API_KEY}" }
    }
  }
}
```

Claude Code expands `${OG_API_KEY}` (and `${VAR:-default}`) from each person's environment when it connects. Two details from its docs: a project server asks for approval the first time someone runs `claude` in the repository, and a few credential variable names such as `ANTHROPIC_API_KEY` deliberately read as empty in `.mcp.json` — so give the key its own name, like `OG_API_KEY`.

### OAuth instead of a key

Claude Code also signs in to remote servers with OAuth. Add the server without `--header`, start `claude`, run `/mcp`, pick shareglint and authenticate in the browser (or run `claude mcp login shareglint`). Shareglint supports dynamic client registration, so you do not need a client ID. You approve the connection on a Shareglint consent screen; it then appears under **Connected apps** in your account settings, where you can disconnect it. Use the key for CI and headless runs, where nobody is there to click through a browser.

## Worked example: og:image for every post of an Astro blog

An Astro blog with 120 Markdown posts in `src/content/blog/` and no social images. Two jobs: new posts get an image automatically, and old posts get one too.

**Step 1 — a signed URL in the layout.** In Claude Code:

> Use the shareglint MCP tools. Call get_template for blog-og, then call create_signed_url once for the post "Hello world" with site "yourblog.com". Write src/lib/og.ts that builds the same signed URL with HMAC-SHA256 from OG_ACCOUNT_ID and OG_SIGNING_SECRET (import.meta.env, server only). Add og:image, og:image:width, og:image:height and twitter:card to src/layouts/BlogPost.astro using the post's title and author. Add a unit test that compares the helper's output with the URL you got from create_signed_url. Do not use the API key in the code.

Claude Code makes two tool calls — `get_template` and `create_signed_url`, both read-only and free — then writes the helper, the layout change and the test, and runs the test. The signing rules (sorted keys, RFC 3986 encoding, the first 32 hex characters of the HMAC) are in the [docs](https://shareglint.com/en/docs#signed); comparing against a URL from the server catches every encoding mistake. The [static sites guide](https://shareglint.com/en/guides/og-images-static-sites-hugo-jekyll-astro) covers the Astro, Hugo and Jekyll versions of this helper.

A signed URL costs nothing until a crawler requests it, and each post's card is one render the first time. The site needs the account id and signing secret at build time — not the API key. Keep both without the `PUBLIC_` prefix: Astro exposes only `PUBLIC_` variables to client-side code, as its [environment variables guide](https://docs.astro.build/en/guides/environment-variables/) explains.

**Step 2 — or files instead of URLs.** If you would rather store image URLs in front matter (for an RSS feed or a CMS), ask for a batch:

> Read every post in src/content/blog/ that has no `image` field. Call get_usage, then create_batch with template blog-og and one row per post: title, author, id = the file slug. Poll get_batch with limit 50 until it is done, and write each row's image URL into that post's front matter as `image`.

The batch is checked against your remaining quota before it starts (`402 batch_quota_exceeded` with `needed` and `available` if it does not fit), rows identical to images you already have are free, and failed rows are refunded. Batch size limits by plan: Free 50, Starter 500, Pro 1,000, Scale 2,000, Business 5,000.

## Troubleshooting

**`/mcp` shows the server as failed.** Run `claude mcp get shareglint` and look at the stored header. A `Bearer ` with nothing after it means `$OG_API_KEY` was empty when you ran `claude mcp add`; remove the server and add it again in a shell where the variable is set.

**Test the key without Claude Code.** This prints the tool list, or `{"error":"unauthorized","message":"Invalid API key."}`:

```bash
curl -s https://shareglint.com/mcp -H "Authorization: Bearer $OG_API_KEY" \
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```

**"Pending approval" on a project server.** Run `claude` interactively in the repository once and approve it. `claude mcp reset-project-choices` clears earlier choices.

**Large `get_batch` output.** Claude Code warns when one tool result passes 10,000 tokens and cuts it at 25,000 by default (`MAX_MCP_OUTPUT_TOKENS` raises it). Ask for pages with `limit` and `after` instead of the whole batch at once.

**A render comes back as `queued`.** The server waits for each image only so long; a slow full-page screenshot or an animated file can return `status: queued` with an `id` instead of a URL. Nothing is lost — ask Claude to call `get_image` with that id. Claude Code's own tool timeout is not the limit here (it defaults to about 28 hours; a per-server `timeout` in `.mcp.json` lowers it).

**`take_screenshot` refuses localhost.** The screenshot browser reaches only public addresses. Screenshot a preview deployment instead.

**`quota_exceeded`.** The month's renders are used up; calls fail rather than bill overage. See [pricing](https://shareglint.com/en/pricing).

## FAQ

### What is the command to add the server to Claude Code?

claude mcp add --transport http shareglint https://shareglint.com/mcp --header "Authorization: Bearer $OG_API_KEY". It adds the server in local scope, for the current project and only for you; add --scope user for every project or --scope project to share it through .mcp.json.

### Is it safe to commit .mcp.json with this server?

Yes, if the header uses a variable: "Authorization": "Bearer ${OG_API_KEY}". Claude Code expands it from each developer's environment, so the file holds no key. Never commit the literal sk_live_ value.

### Can Claude Code sign in with OAuth instead of an API key?

Yes. Add the server without the header and run /mcp in Claude Code to authenticate in the browser. Shareglint supports dynamic client registration, so no client ID is needed. A key is simpler in CI and headless runs.

### Does it work in claude -p and CI?

Yes. In claude -p runs, servers from a project's .mcp.json load without the approval prompt, and the API key comes from the environment, for example a CI secret named OG_API_KEY.
