CtrlK
BlogDocsLog inGet started
Tessl Logo

punkdev/cc2oc

Add and ship OpenCode support for one Claude Code plugin at a time. Includes core migration to a reviewable `opencode-plugin/` adapter, maintainer-facing docs, and follow-up CI/versioning setup for package publishing or skill-copy drift checks.

92

1.25x
Quality

92%

Does it follow best practices?

Impact

97%

1.25x

Average score across 2 eval scenarios

SecuritybySnyk

Passed

No known issues

Overview
Quality
Evals
Security
Files

mcp-migration.mdskills/migrate-plugin/references/

MCP Migration

Use this when a Claude plugin or project includes MCP server configuration.

Key Distinction

Claude plugins can bundle MCP servers through .mcp.json at the plugin root or inline mcpServers in .claude-plugin/plugin.json. OpenCode MCP servers are configured under the mcp key in OpenCode config (opencode.json or opencode.jsonc) and managed with opencode mcp commands.

Do not assume an OpenCode npm plugin package can bundle MCP config the same way Claude plugins can. Generate or propose OpenCode config entries separately from opencode-plugin/ package metadata.

Source Locations

Inspect all of these:

  • .mcp.json with a top-level mcpServers object.
  • .claude-plugin/plugin.json with inline mcpServers.
  • Existing opencode.json or opencode.jsonc with an mcp object.
  • Local server scripts referenced by MCP command values.

Treat .mcp.json and plugin.json.mcpServers as Claude migration input. Do not generate .mcp.json for OpenCode support.

Destination Policy

Use the existing OpenCode config file if present:

  1. If opencode.jsonc exists, propose/merge into opencode.jsonc.
  2. Else if opencode.json exists, propose/merge valid JSON into opencode.json.
  3. Else propose/create opencode.jsonc for project-scoped OpenCode MCP config.

Do not generate MCP config into .opencode/ by default. .opencode/ is active project config for plugins, commands, agents, skills, and similar surfaces; MCP belongs under the mcp key in OpenCode config.

Do not edit global OpenCode config unless the user explicitly asks for global setup. For global setup, provide commands or snippets for the user-visible global config path.

Mapping Rules

ClaudeOpenCodeNotes
.mcp.json.mcpServersopencode.jsonc.mcpMove server map under mcp.
.claude-plugin/plugin.json.mcpServersopencode.jsonc.mcpTreat inline plugin MCP as migration input too.
command: "cmd" + args: [...]command: ["cmd", ...args]OpenCode local command is an array.
envenvironmentRename key.
no type with commandtype: "local"Infer local when Claude server has command.
type: "http" or urltype: "remote", urlPreserve headers if present; verify auth.
${CLAUDE_PLUGIN_ROOT}explicit repo/package pathDecide where equivalent server files live before rewriting.
${CLAUDE_PLUGIN_DATA}OpenCode/XDG-safe state path or env varDo not point OpenCode state to Claude plugin data.
secrets in env or headersplaceholders / documented env varsDo not inline secrets into generated config.
OAuth remote serversOpenCode remote MCP OAuth flowVerify with opencode mcp auth <name> when needed.

Local Example

Claude:

{
  "mcpServers": {
    "database-tools": {
      "command": "${CLAUDE_PLUGIN_ROOT}/servers/db-server",
      "args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
      "env": {
        "DB_URL": "${DB_URL}"
      }
    }
  }
}

OpenCode config snippet:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "database-tools": {
      "type": "local",
      "command": ["./opencode-plugin/servers/db-server", "--config", "./opencode-plugin/config.json"],
      "enabled": true,
      "environment": {
        "DB_URL": "${DB_URL}"
      }
    }
  }
}

Only use ./opencode-plugin/... if the server files are actually copied or packaged there. Otherwise point at the existing safe repo path.

Remote Example

OpenCode config snippet:

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

If the remote server uses OAuth, document the required OpenCode auth step:

opencode mcp auth stripe

Conflict Handling

If opencode.json or opencode.jsonc already contains an mcp entry with the same name:

  1. Do not overwrite silently.
  2. Compare command/url, environment, headers, enabled, and timeout values.
  3. Ask whether to keep existing, update existing, or add a renamed MCP entry.
  4. Report the decision in the final summary.

Secrets

Never inline secrets from the current environment. Preserve placeholders like ${API_KEY} or document required environment variables.

If a Claude config contains literal-looking secrets, warn the user before copying them and prefer replacing them with placeholders.

Verification

When OpenCode is available:

  • Run or ask the user to run opencode mcp list.
  • For OAuth remote servers, run or ask for opencode mcp auth <name>.
  • Prompt OpenCode to use the named MCP tool if the environment can safely start the server.

If OpenCode is not available, validate the config shape and document unverified runtime behavior.

README.md

tile.json