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_urlto 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_screenshotwith aselectorcaptures one element,devicea phone layout. - Backfill images. "For every post in content/ without an image, render one and add the URL to its front matter" —
create_batchwith rows the agent builds from your files, thenget_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:
list_templatesandget_templatereturn the fields ofblog-og—title,eyebrow,author,site,date,reading_time,photo,accent,theme.create_signed_urlwith{"template": "blog-og", "fields": {"title": "Hello world", "site": "yourblog.com"}}returns a URL likehttps://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.- 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. - 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] },
};
}
- 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 (encodeURIComponentleaves! ' ( ) *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.