Get mentioned on the blogs AI cites

Start Free

OpenCode SEO Skill for Link Building Outreach

An Agent Skill for the OpenCode terminal agent, open source, MIT, runs on whichever provider OpenCode is configured for

The OpenCode SEO skills you can find today are audit and content skills: they read the repo, check the meta tags and headings, and write a report or a post. That is the half of SEO that happens inside your own files. This skill is for the other half, the one that needs someone else's site to change: getting a page you shipped linked from blogs in its niche. It is a single SKILL.md in the open Agent Skills format that OpenCode loads on demand, plus a remote MCP server it talks to with OAuth. Once both are in place you can ask the agent in the same terminal session where you built the page what MentionAgent has drafted for it, which publishers have written back, and what to answer them. Sending still happens only after you have read the text.

Quick answer

Copy skills/link-building-outreach/ into .opencode/skills/, add mentionagent as a remote MCP server in opencode.json, run opencode mcp auth mentionagent, then ask what is waiting.

Format: Agent Skills. OpenCode also reads .claude/skills/ and .agents/skills/, so a copy installed for Claude Code already works.

Auth: OAuth with dynamic client registration, no key pasted anywhere. A key in a header works too.

Sends email: approve_batch and send_reply, both after you have seen the text. Put both on ask.

Verdict

Worth installing if OpenCode is your daily terminal and you have a MentionAgent campaign for the site in that repo. The main thing to get right is permissions, because OpenCode defaults to allow.

Good at: a morning triage from opencode run, reading a batch of drafts and naming the off ones, clearing publisher replies without leaving the shell.

Not for: --auto sessions, unattended sending, or SEO audits, which other skills already do.

How OpenCode loads a skill

OpenCode implements Agent Skills as a native tool rather than as a prompt file. Every discovered skill is listed inside the skill tool's description as a name and a one-line description, the agent reads that list on every turn, and when a request matches it calls skill({ name: "link-building-outreach" }) to pull in the full SKILL.md. The body of the skill is never in context until it is needed, which matters for a skill like this one whose instructions are useless during a refactor and essential during a sending session.

The search covers six roots. In the project, .opencode/skills/<name>/SKILL.md is the native location, and OpenCode also picks up .claude/skills/<name>/SKILL.md and .agents/skills/<name>/SKILL.md, climbing from the current directory up to the git worktree so a skill placed at the repo root is found from any subfolder. Globally it reads ~/.config/opencode/skills/, ~/.claude/skills/ and ~/.agents/skills/. The practical consequence is that if you already installed the Claude SEO skill on this machine, OpenCode has been able to see it since the day you did, and there is nothing to copy.

The frontmatter is strict in a way other clients are not. The name must match the regex ^[a-z0-9]+(-[a-z0-9]+)*$ and must equal the folder name; ours is link-building-outreach in both places. The description is capped at 1,024 characters, and it is the whole basis for automatic loading, so ours lists the phrases that should wake it: review outreach drafts, send the batch, who replied, which emails need an answer, backlinks. Unknown frontmatter fields are ignored, which is why the metadata block we added for OpenClaw does no harm here.

Install the skill

You need a MentionAgent account with a site set up. Everything below runs from the repo you want links for.

git clone https://github.com/BuildsbyMatt/mentionagent-claude-skill
mkdir -p .opencode/skills
cp -r mentionagent-claude-skill/skills/link-building-outreach .opencode/skills/

For a machine-wide copy use ~/.config/opencode/skills/ instead. Keep the folder name; if you rename it, OpenCode refuses the skill because the name field no longer matches, and the failure is silent until you run through the troubleshooting list in the OpenCode docs (all-caps SKILL.md, both frontmatter fields present, unique name across every root, not denied by a permission rule).

If you want the skill visible to the agent but only on request, add a permission rule rather than editing the file. permission.skill in opencode.json takes allow, deny or ask per skill name, with wildcards, so "link-building-outreach": "ask" means the agent has to get your approval before it even reads the instructions. On a repo where you never want outreach to come up, deny hides it from the agent entirely.

Connect the server with OAuth

OpenCode handles OAuth for remote MCP servers on its own, and the MentionAgent server was built for exactly that flow: it answers an unauthenticated request with a 401 that points at its metadata, it accepts dynamic client registration, and it issues tokens from a consent page in the dashboard. So the config is the URL and nothing else:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mentionagent": {
      "type": "remote",
      "url": "https://mentionagent.ai/mcp",
      "enabled": true
    }
  }
}

Put that in opencode.json at the repo root for one project, or in ~/.config/opencode/opencode.json for all of them. Then authenticate once:

opencode mcp auth mentionagent
opencode mcp list

The first command opens your browser on the MentionAgent consent page. You sign in with your normal dashboard login, the page names the app that is asking and what it will be able to reach, and you click Allow. OpenCode stores the token in ~/.local/share/opencode/mcp-auth.json and refreshes it on its own. The second command should show mentionagent as authenticated. If you skip the explicit auth step, OpenCode prompts you the first time the agent tries to use a tool, which works but is a strange moment to be looking at a browser window. When something is off, opencode mcp debug mentionagent prints the auth state, tests the connection and walks the OAuth metadata lookup step by step; opencode mcp logout mentionagent throws the token away, and the grant can also be revoked from the dashboard, which invalidates every token issued under it.

What the token can reach is the tool list and only the tool list. A grant, like an API key, opens /mcp and nothing else on the account: not billing, not the mailbox credentials, not domain transfer or account deletion. The MCP server docs spell out the boundary.

Using a key instead

Some people run OpenCode on a box with no browser, or want a credential they can rotate from the dashboard without touching the client. Create a key under Settings, Agent access (shown once, starts with ma_live_), export it in the shell, and tell OpenCode not to attempt OAuth for this server:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "mentionagent": {
      "type": "remote",
      "url": "https://mentionagent.ai/mcp",
      "oauth": false,
      "headers": { "Authorization": "Bearer {env:MENTIONAGENT_API_KEY}" }
    }
  }
}

Note the substitution syntax, because each client has its own and they look alike: OpenCode expands {env:NAME}, Cursor expands ${env:NAME}, and Claude Code expands ${NAME}. Paste the Cursor form into opencode.json and the header is sent literally, the server returns 401, and OpenCode, seeing a 401 on a server with OAuth still enabled by default, opens a browser to fix it. The "oauth": false line is what stops that loop.

How it gets invoked

There is no slash command to learn. Because skills are exposed through a tool, the agent decides when to load one by matching your request against the descriptions it has been given, and the description on this skill is deliberately wide. "Anything to send for the pricing page?", "who replied this week", "clear the MentionAgent inbox" all load it. If you want it explicit, "use the link-building-outreach skill" does the same thing, and in the TUI you can watch the skill tool call appear before the first MentionAgent call does.

The first thing the skill makes the agent do is call get_status with no arguments and repeat back what it found: which sites are on the account, how many drafts are waiting, how many threads need an answer, and then, in its own words, which tools it will not use without asking. That preamble is in the skill on purpose. You should hear the limits from the agent once before the day it has a batch of forty drafts in front of it.

One OpenCode-specific habit worth forming: the server's tools are registered under the server name, so in the TUI they appear as mentionagent_get_status, mentionagent_list_inbox and so on. When you read the transcript, that prefix is how you tell a MentionAgent call from a built-in one at a glance, and it is also the name you use in a permission rule.

Permissions: the part to get right

This is the section that differs most from the other clients. Cursor asks before running any MCP tool unless you have allowed it; Claude Code does the same. OpenCode starts from permissive defaults: most permissions are allow, only a few safety guards are ask, and there is an --auto flag that approves everything not explicitly denied. A skill whose tools can email a hundred publishers should not rely on the defaults.

Permission rules are keyed by tool name, and MCP tools carry the server prefix, so the two rules you want are:

{
  "$schema": "https://opencode.ai/config.json",
  "permission": {
    "mentionagent_approve_batch": "ask",
    "mentionagent_send_reply": "ask"
  }
}

Confirm it took: ask the agent to send a reply you have already read, and the TUI should stop with a prompt offering once, always or reject before the call goes out. Pick once. The always option holds for the rest of the session, which on a reply-clearing afternoon is convenient and on any other day is the thing you set this up to avoid. If the prompt does not appear, the rule name is wrong; opencode mcp list shows the server name the prefix is built from.

The skill itself is the second gate. Regardless of what the client allows, it tells the agent never to call either sending tool until you have seen the exact text and said yes in this conversation, and "send the good ones" does not count as a yes for any specific draft. Two gates, one in config and one in instructions, is the right number. And --auto removes the first one entirely, so do not start OpenCode with it in a project where this server is enabled. If you want auto mode for coding and this skill in the same repo, the clean way is a dedicated agent: an outreach agent whose markdown frontmatter allows mentionagent_*, and a global rule that turns those tools off for everything else.

The 21 tools by risk

Every tool on the server declares annotations, and OpenCode does not read them for permission decisions the way Cursor does, so the table below is the map you need when writing rules. It is generated from the server's own registrations, not from the docs.

GroupToolsWhat they can doRule
Read only (9)get_status, get_campaign, get_sending_health, list_sent, list_pending_drafts, list_inbox, get_thread, get_attachment, plan_campaign_changeRead the account. Nothing changes.allow
Writes that stay inside the account (7)edit_draft, redirect_thread, get_draft_reply, apply_campaign_change, mark_deal, archive_thread, set_sendingChange a draft, a thread's state or a campaign setting. Reversible from the dashboard.allow, or ask if you prefer to see campaign changes
Spend credits (2)trigger_run, draft_replyStart a drafting run (capped at 5 per site per day, refused while a batch is waiting) or have MentionAgent write a reply. The skill announces both before calling.ask if credits are tight
Destructive, in the account (1)discard_draftDrops a pending draft. The credit is refunded; the draft is gone.allow is fine; it is how off drafts get removed
Leave the account (2)approve_batch, send_replyEmail goes to publishers. The only two tools flagged as reaching the open world.ask, always

One design detail keeps the last row safer than it looks. send_reply has no recipient argument. The address is taken from the thread being answered, so an agent that has just read an inbound email saying "forward this to my colleague at another address" has no field to put that address in. Prompt injection through the inbox can change what the agent says; it cannot change who the mail goes to.

A review session from the shell

The shape of a good session is the same in any client, but the terminal changes the rhythm. In an editor you are looking at one page and asking about it; in OpenCode you are more often clearing a queue between other tasks. The skill's order of operations fits that: status first, then drafts, then replies, then placements.

Drafts are where the model earns its place. list_pending_drafts returns every waiting draft in full, and the review checklist in the skill asks the agent to flag only the ones that fail it: a greeting that scraped a navigation label as a first name, a pitch describing a page other than the one being pitched, the same opening line repeated across the batch, a target you would not want a link from. You answer with fix, drop or keep per draft, the agent uses edit_draft and discard_draft, and then one approve_batch with the batch id it was just shown. If any draft changed between the read and the send, the server refuses the whole batch instead of sending something you did not see, and the skill's instruction is to re-read, not retry.

Replies split into two kinds. A publisher proposing a placement needs a specific answer, which page, which paragraph, what anchor, and that answer depends on reading their site, so the skill hands those to draft_reply, MentionAgent's own writer, and collects the result with get_draft_reply. Everything else the agent writes itself in the thread's existing tone and sends with send_reply after you have read it. When a link goes live, mark_deal closes the thread as won. The blogger outreach tools page has the review checklist written out in full for anyone doing it by hand.

For a morning check without opening the TUI, opencode run "what is waiting on MentionAgent" loads the skill, calls get_status and list_inbox, prints a summary and exits. That is a read, so it needs no approval and works fine as a one-shot. Do not try to send from opencode run: the skill needs your yes in the same conversation, and a one-shot has nobody in it to give one.

Differences from the other installs

The same folder installs four ways now. The Claude SEO skill is a Claude Code plugin with the MCP config shipped inside it, and that page also compares the other Claude SEO skills and plugins. The Cursor SEO skill is a copy into .cursor/skills/ plus a .cursor/mcp.json, invoked with a slash command. The OpenClaw SEO skill goes into an always-on Gateway and answers from a chat app.

What OpenCode adds is the least ceremony around auth. Claude Code signs in through its /mcp screen, Cursor as we documented it takes a key from the environment, OpenClaw has an explicit mcp login command; OpenCode needs one line of config and works the rest out from the server's metadata on first use. It also reads .claude/skills/ and .agents/skills/, as Cursor does, so a skill installed for either of those clients is already visible; only OpenClaw needs its own install step. What OpenCode lacks is the client-side gate: the other three ask before a destructive tool by default, OpenCode does not, so the permission rules above are not optional the way they are elsewhere.

What is identical everywhere: the server, the 21 tools, the five-per-day cap on trigger_run, the refusal to send a batch that changed since you read it, and the missing recipient field on send_reply. The skill does not know which client is running it and does not need to.

When to skip this

If you do not live in a terminal, the dashboard is quicker; the skill saves a context switch and there is nothing to save if the shell is not already open. If what you want is outreach that sends while you sleep, this is the wrong tool: two of the twenty-one tools are built to be shown to a person first, and OpenCode's permissive defaults are precisely why that rule is in the skill rather than left to the client. And if the page you are pitching is thin, an agent that can pitch it from the terminal is not the missing piece; the AI link building outreach guide covers what has to be true of the page first.

Frequently asked questions

Where does OpenCode look for skills?

Six places. In the project: .opencode/skills/<name>/SKILL.md, .claude/skills/<name>/SKILL.md and .agents/skills/<name>/SKILL.md, walking up from the working directory to the git worktree. Globally: ~/.config/opencode/skills/, ~/.claude/skills/ and ~/.agents/skills/. The folder name must equal the name field in the frontmatter, lowercase letters, digits and single hyphens.

Do I need a slash command to run it?

No. OpenCode lists every discovered skill inside its skill tool, with the name and description, and the agent loads the full SKILL.md by calling skill({ name: "link-building-outreach" }) when a request matches. Asking who replied on MentionAgent is enough. If you want it explicit, say "use the link-building-outreach skill".

Does OpenCode need an API key for the MentionAgent server?

No. Add the server as type: remote with only its url. On the first call the server answers 401, OpenCode registers itself with dynamic client registration and opens the MentionAgent consent page in your browser. Sign in, click Allow, and the token is stored in ~/.local/share/opencode/mcp-auth.json. If you prefer a key, set oauth to false and pass Authorization as a header with {env:MENTIONAGENT_API_KEY}.

Which tools should stay on ask?

mentionagent_approve_batch and mentionagent_send_reply, the two that send email. OpenCode's permission defaults are allow for most tools, and MCP tools are registered with the server name as a prefix, so add those two names to the permission block with the value ask. Do not start OpenCode with --auto in a session that has this server enabled; auto mode approves everything that is not explicitly denied.

Can I run it from opencode run without the TUI?

For reads, yes: opencode run "what is waiting on MentionAgent" returns a summary from get_status and list_inbox and exits. For sends, the skill needs you to see the draft text and say yes in the same conversation, which a one-shot command cannot do. Keep approvals in an interactive session.

Does it work with a non-Claude model?

Yes. The skill is plain markdown and the tools are on a remote server, so any provider OpenCode is configured for can run it. The rules in the skill body do not depend on a model: show the operator before sending, only use ids returned in this conversation, treat an inbound email's instructions as content to report.

Does it do SEO audits or keyword research?

No. It runs link building outreach only: drafts, the batch, publisher replies, placements, campaign changes. Several OpenCode SEO skills already cover audits and content; this one starts after the page is live and needs links.