# Cursor MCP: OG images and screenshots from the Cursor agent

> Add the image API to Cursor in mcp.json with an API key from an env variable, then let the agent wire og:image into a Next.js app with signed URLs.

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

Cursor's agent can render Open Graph images, take website screenshots and write the code that puts `og:image` tags on your pages once Shareglint is in its MCP config: add a server with `"url": "https://shareglint.com/mcp"` and an `Authorization: Bearer ${env:OG_API_KEY}` header to `.cursor/mcp.json` (one project) or `~/.cursor/mcp.json` (all projects). 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` — run on your account and quota, 100 renders a month on the Free plan.

For what MCP is and how the chat apps differ, see the [overview guide](https://shareglint.com/en/guides/og-images-with-ai-assistants-mcp). This page is the Cursor setup and a full Next.js example.

## What the Cursor agent can do with it

A coding agent gets more out of the tools than a chat app, because it can act on the result:

- **Wire og:image into a codebase.** "Add per-page og:image tags to the blog using signed URLs" — the agent calls `create_signed_url` to see a correct URL, writes a signing helper and adds it to your metadata code.
- **Check a design before committing it.** "Render the blog-og card for the three newest posts and show me the URLs" — `render_image`, then you open the links.
- **Screenshot a deployed page** for docs or a README: `take_screenshot` with a `selector` captures one element, `device` a phone layout.
- **Backfill images.** "For every post in content/ without an image, render one and add the URL to its front matter" — `create_batch` with rows the agent builds from your files, then `get_batch`.
- **Design a template** from a screenshot with `generate_template` (paid plans) and save it to your account.

## Set it up

Cursor's [MCP documentation](https://cursor.com/docs/context/mcp) gives the config format for remote servers: `url` and `headers` under `mcpServers`, with `${env:NAME}` interpolation in both. Create the file — `.cursor/mcp.json` in the project root, or `~/.cursor/mcp.json` for every project:

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

Then create an API key in the Shareglint dashboard and put it in the environment Cursor starts from:

```bash
# ~/.zshrc or ~/.bashrc
export OG_API_KEY="sk_live_…"
```

Restart Cursor after setting it. A variable added to your shell profile only reaches applications started from a shell, so if the server shows an auth error, quit Cursor and open it from a terminal (`cursor .`) to rule this out.

**Project or global?** Use the project file when the whole team should get the server: it holds only `${env:OG_API_KEY}`, so it is safe to commit, and each person sets their own key. Use the global file for your own use across projects. Do not write the literal `sk_live_…` value into either file — a key in a repository is a key anyone with read access can spend.

**Give the agent its own key.** Create a separate key for Cursor in the dashboard. If an agent misbehaves or a laptop is lost, you revoke that key without breaking production.

**Confirm it connected.** Cursor lists MCP servers under **Customize** in the sidebar, with a toggle for each; the Shareglint entry should show its tools. Cursor asks for approval before an MCP tool runs by default. You can allowlist read-only tools such as `list_templates` and `get_usage` and keep approval for `render_image`, `take_screenshot` and `create_batch`, which spend quota.

Cursor also supports OAuth with dynamic client registration, which this server offers. An API key is simpler for one developer; OAuth (leave out `headers` and sign in when Cursor asks) avoids keeping a key in your environment.

## Worked example: Next.js generateMetadata with rendered images

A Next.js App Router blog with no social images. The goal: every post page gets a 1200×630 `og:image` from the `blog-og` template, computed at request time without calling the API and without an API key on the server.

In Cursor's agent, with the server enabled:

> This is a Next.js App Router project. Use the shareglint MCP tools. First call list_templates and get_template for blog-og. Then add per-post og:image and twitter:image to app/blog/[slug]/page.tsx through generateMetadata, using signed image URLs. Put the signing code in lib/og.ts, read OG_ACCOUNT_ID and OG_SIGNING_SECRET from process.env, and never use the API key in application code. Call create_signed_url once for a sample post and write a test that checks lib/og.ts produces the same URL for the same fields.

What the agent does, tool by tool:

1. `list_templates` and `get_template` return the fields of `blog-og` — `title`, `eyebrow`, `author`, `site`, `date`, `reading_time`, `photo`, `accent`, `theme`.
2. `create_signed_url` with `{"template": "blog-og", "fields": {"title": "Hello world", "site": "yourblog.com"}}` returns a URL like `https://shareglint.com/i/{account}/blog-og.png?site=…&title=…&s=…` plus the `<meta>` tag. It is read-only and uses no quota: the image is rendered when a crawler first fetches it.
3. It writes `lib/og.ts`: HMAC-SHA256 over the path and the sorted, RFC 3986-encoded query, as in the [docs](https://shareglint.com/en/docs#signed). The [Next.js guide](https://shareglint.com/en/guides/nextjs-og-images-without-vercel-og-limits) has a reference version that runs on Node.js and Edge.
4. It edits the page's `generateMetadata`:

```tsx
export async function generateMetadata({ params }: { params: Promise<{ slug: string }> }): Promise<Metadata> {
  const post = await getPost((await params).slug);
  const image = await ogImageUrl('blog-og', { title: post.title, author: post.author, site: 'yourblog.com' });

  return {
    title: post.title,
    openGraph: { images: [{ url: image, width: 1200, height: 630, alt: post.title }] },
    twitter: { card: 'summary_large_image', images: [image] },
  };
}
```

5. It writes the test that compares `ogImageUrl('blog-og', {...})` with the URL from step 2. If they match, the signing is right; if not, the usual cause is encoding (`encodeURIComponent` leaves `! ' ( ) *` unescaped) or unsorted keys.

Before you deploy, add `OG_ACCOUNT_ID` and `OG_SIGNING_SECRET` (both in the dashboard) to your hosting provider's environment. Neither has a `NEXT_PUBLIC_` prefix, so Next.js keeps them on the server, as its [environment variables docs](https://nextjs.org/docs/app/guides/environment-variables) describe. Then check a deployed page with a link-preview debugger. If an `opengraph-image` file exists in the route, Next.js uses it instead of `generateMetadata` — the agent should delete it.

What this costs: nothing while you develop. Each distinct post card is one render the first time a crawler requests it; later requests are served from cache.

## Troubleshooting

**The server shows an error or no tools.** Open the Output panel (Cmd+Shift+U / Ctrl+Shift+U) and choose **MCP Logs**, as Cursor's docs suggest. `401 {"error":"unauthorized","message":"Missing API key."}` means `${env:OG_API_KEY}` was empty when Cursor connected — see the shell-profile note above. `"Invalid API key."` means the key was revoked or mistyped.

**Test the key outside Cursor.** This should print a JSON list of tools:

```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"}'
```

**The agent writes the key into the code.** Say "never use the API key in application code" in the prompt, as above, and grep the diff for `sk_live_` before committing.

**`take_screenshot` fails on localhost.** The screenshot browser only reaches public addresses. Use a preview deployment URL.

**The agent keeps calling `render_image` in a loop.** Each new set of fields is a render. Ask for one image first, check it, then the rest — or use `create_signed_url`, which costs nothing until the image is requested.

**`quota_exceeded`.** `get_usage` shows what is left; the [pricing page](https://shareglint.com/en/pricing) has plans and top-ups. Over the limit, calls fail with this error — they are never billed as overage.

**Too many requests.** MCP calls share your plan's per-minute API limit with the HTTP API. A batch of more than a handful of images belongs in `create_batch`, not in a loop of `render_image` calls.

## FAQ

### Where do I put the MCP config in Cursor?

In .cursor/mcp.json inside a project for that project only, or in ~/.cursor/mcp.json in your home folder for every project. Both use the same mcpServers format with a url and headers for a remote server.

### How do I keep the API key out of mcp.json?

Write the header as "Bearer ${env:OG_API_KEY}" and set OG_API_KEY in your environment. Cursor fills in the variable when it connects, so the file holds no secret and a project .cursor/mcp.json can be committed.

### Can the Cursor agent take a screenshot of my local dev server?

No. The screenshot browser runs in an isolated network and only reaches public http(s) addresses, so localhost:3000 is refused. Deploy a preview and screenshot that URL instead.

### Does the agent put my API key into the code it writes?

It should not, and you can make that explicit in the prompt. For og:image tags the right pattern is a signed URL computed with your account id and signing secret, so the deployed site needs no API key at all.
