Menu
Sign up

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 November 4, 2026 · 6 min read

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. 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 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:

{
  "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:

# ~/.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. The Next.js guide has a reference version that runs on Node.js and Edge.
  4. It edits the page's generateMetadata:
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] },
  };
}
  1. 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 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:

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 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.