@dodopayments/opencode-plugin 0.6.5 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md
CHANGED
|
@@ -42,7 +42,7 @@ claude plugins marketplace add dodopayments/dodo-agent-plugin
|
|
|
42
42
|
claude plugins install dodopayments@dodopayments
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
The API MCP server
|
|
45
|
+
The API MCP server signs in with OAuth, so there is no API key to paste. The first time your agent calls a Dodo tool, a Dodo Payments consent page opens in your browser: pick the business, mode and permissions. See [Sign-in and access](#sign-in-and-access).
|
|
46
46
|
|
|
47
47
|
### Codex CLI
|
|
48
48
|
|
|
@@ -122,7 +122,7 @@ OpenCode distributes via npm. Add the plugin to your `opencode.json`:
|
|
|
122
122
|
}
|
|
123
123
|
```
|
|
124
124
|
|
|
125
|
-
Restart OpenCode. Both MCP servers (`dodopayments-api`, `dodo-knowledge`) are registered automatically via the plugin's `config` hook as native remote servers. No manual `mcp` block required. Run `opencode mcp auth dodopayments-api` to
|
|
125
|
+
Restart OpenCode. Both MCP servers (`dodopayments-api`, `dodo-knowledge`) are registered automatically via the plugin's `config` hook as native remote servers. No manual `mcp` block required. Run `opencode mcp auth dodopayments-api` to open the Dodo Payments consent page for the API server.
|
|
126
126
|
|
|
127
127
|
**Skills need the package installed locally plus one extra line.** OpenCode does not scan installed packages for skills, so point it at the package's `skills/` directory yourself. `skills.paths` entries resolve against the project directory, so the package must be present in the project's `node_modules` - OpenCode's own plugin cache is not the same location:
|
|
128
128
|
|
|
@@ -146,26 +146,6 @@ Verify with `opencode run "List every skill available to you by name."` - you sh
|
|
|
146
146
|
|
|
147
147
|
> Versions before 0.5.0 documented these skills as auto-discovered. They were not: nothing in OpenCode scans an installed package, so OpenCode users had MCP servers but no skills. Setting `config.skills` from the plugin's `config` hook does not fix this either - the skill index is built before `config` hooks run, so it never registers anything.
|
|
148
148
|
|
|
149
|
-
If you prefer the local stdio API server with your own API key instead of the default remote OAuth server, declare `dodopayments-api` yourself in `opencode.json` - your entry wins over the plugin default:
|
|
150
|
-
|
|
151
|
-
```jsonc
|
|
152
|
-
{
|
|
153
|
-
"plugin": ["@dodopayments/opencode-plugin"],
|
|
154
|
-
"mcp": {
|
|
155
|
-
"dodopayments-api": {
|
|
156
|
-
"type": "local",
|
|
157
|
-
"command": ["npx", "-y", "dodopayments-mcp@latest"],
|
|
158
|
-
"environment": {
|
|
159
|
-
"DODO_PAYMENTS_API_KEY": "dodo_test_...",
|
|
160
|
-
"DODO_PAYMENTS_WEBHOOK_KEY": "whsec_...",
|
|
161
|
-
"DODO_PAYMENTS_ENVIRONMENT": "test_mode"
|
|
162
|
-
},
|
|
163
|
-
"enabled": true
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
149
|
## Included Skills
|
|
170
150
|
|
|
171
151
|
**Getting started**
|
|
@@ -227,34 +207,29 @@ Skills source: [`dodopayments/skills`](https://github.com/dodopayments/skills),
|
|
|
227
207
|
|
|
228
208
|
Both servers speak Streamable HTTP over HTTPS, and every manifest dials them natively - no `npx mcp-remote` bridge and no Node dependency. The canonical `mcp.json` uses the spec's `type: "streamable-http"`; the generated `.mcp.json` (Claude Code, Cursor, VS Code, Grok Build, Devin, Goose, Droid) uses the same endpoints spelled `type: "http"`, the name that dialect uses; Muse, Antigravity, Junie and Gemini get their own spellings from the generator.
|
|
229
209
|
|
|
230
|
-
##
|
|
210
|
+
## Sign-in and access
|
|
231
211
|
|
|
232
|
-
|
|
212
|
+
The API MCP server signs in with OAuth. No config in this plugin holds an API key, and no step asks you to paste one.
|
|
233
213
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
214
|
+
1. The first tool call on `dodopayments-api` opens a Dodo Payments consent page in your browser. Some clients start the sign-in from a command instead: `codex mcp login dodopayments-api`, `opencode mcp auth dodopayments-api`, `muse mcp login dodopayments-api`, or `/mcp` in Claude Code.
|
|
215
|
+
2. Sign in, then pick the business, the mode (test or live) and the permissions to grant.
|
|
216
|
+
3. The client stores the token. To switch to another business or mode, sign out of the server in your client and sign in again.
|
|
237
217
|
|
|
238
|
-
|
|
218
|
+
To review or revoke access, open the Dodo Payments dashboard at **Settings > Connected Apps**.
|
|
239
219
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
"DODO_PAYMENTS_ENVIRONMENT": "${user_config.dodo_environment}"
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
}
|
|
220
|
+
Every client config in this repo dials `https://mcp.dodopayments.com/mcp` directly, sets no headers, and lets the client run OAuth discovery itself. A host that cannot run MCP OAuth gets `dodo-knowledge` only - today that is the xAI API (see [Grok](./docs/clients/grok.md)).
|
|
221
|
+
|
|
222
|
+
### Dodo CLI
|
|
223
|
+
|
|
224
|
+
The skills use the Dodo CLI for local webhook testing. It uses the same OAuth sign-in:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
npm i -g dodopayments-cli # browser sign-in needs v3.7.0 or later
|
|
228
|
+
dodo login # sign in with the browser
|
|
229
|
+
dodo whoami # show the stored sign-in
|
|
255
230
|
```
|
|
256
231
|
|
|
257
|
-
|
|
232
|
+
Over SSH or with no browser, run `dodo login --device` in place of `dodo login`, and enter the code on another device. To sign out when you finish, run `dodo logout all`.
|
|
258
233
|
|
|
259
234
|
## Enable / disable individual MCP servers
|
|
260
235
|
|
|
@@ -27,7 +27,7 @@ Restart OpenCode.
|
|
|
27
27
|
- Both MCP servers are registered automatically via the plugin's `config` hook.
|
|
28
28
|
- The `skills.paths` entry is what makes the skills visible - OpenCode does not scan installed packages for skills. The path resolves against the **project** directory, not OpenCode's plugin cache, which is why the local install above is required. An absolute path works too and avoids that requirement.
|
|
29
29
|
- The plugin module exports only its default function. OpenCode's loader throws `Plugin export is not a function` on any non-function named export, skips the plugin, and swallows the error - leaving you with no MCP servers. Verified on OpenCode 1.18.15.
|
|
30
|
-
- The first call to `dodopayments-api` opens a browser
|
|
30
|
+
- The first call to `dodopayments-api` opens a Dodo Payments consent page in the browser: pick the business, mode and permissions. `opencode mcp auth dodopayments-api` starts the same sign-in. To review or revoke access, open the dashboard at **Settings > Connected Apps**. `dodo-knowledge` needs no auth.
|
|
31
31
|
|
|
32
32
|
Verify the install:
|
|
33
33
|
|
|
@@ -67,26 +67,23 @@ Persist the toggle by exporting the var in your shell profile or a project `.env
|
|
|
67
67
|
|
|
68
68
|
## Overriding the defaults
|
|
69
69
|
|
|
70
|
-
The plugin registers MCPs with nullish-assign semantics, so anything you declare in your own `opencode.json` wins. Example -
|
|
70
|
+
The plugin registers MCPs with nullish-assign semantics, so anything you declare in your own `opencode.json` wins. Example - keep the API server declared but turned off:
|
|
71
71
|
|
|
72
72
|
```jsonc
|
|
73
73
|
{
|
|
74
74
|
"plugin": ["@dodopayments/opencode-plugin"],
|
|
75
75
|
"mcp": {
|
|
76
76
|
"dodopayments-api": {
|
|
77
|
-
"type": "
|
|
78
|
-
"
|
|
79
|
-
"
|
|
80
|
-
"DODO_PAYMENTS_API_KEY": "dodo_test_...",
|
|
81
|
-
"DODO_PAYMENTS_WEBHOOK_KEY": "whsec_...",
|
|
82
|
-
"DODO_PAYMENTS_ENVIRONMENT": "test_mode"
|
|
83
|
-
},
|
|
84
|
-
"enabled": true
|
|
77
|
+
"type": "remote",
|
|
78
|
+
"url": "https://mcp.dodopayments.com/mcp",
|
|
79
|
+
"enabled": false
|
|
85
80
|
}
|
|
86
81
|
}
|
|
87
82
|
}
|
|
88
83
|
```
|
|
89
84
|
|
|
85
|
+
The API server has no API key mode. Declare it only as the remote server above, which signs in with OAuth.
|
|
86
|
+
|
|
90
87
|
`dodo-knowledge` continues to be registered by the plugin unless you declare it explicitly too.
|
|
91
88
|
|
|
92
89
|
## License
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ The [Dodo Payments agent plugin](https://github.com/dodopayments/dodo-agent-plug
|
|
|
12
12
|
| Server | URL | Auth | Use it for |
|
|
13
13
|
|--------|-----|------|------------|
|
|
14
14
|
| `dodo-knowledge` | `https://knowledge.dodopayments.com/mcp` | None | Semantic search over Dodo Payments docs, API reference and SDK docs |
|
|
15
|
-
| `dodopayments-api` | `https://mcp.dodopayments.com/mcp` | OAuth
|
|
15
|
+
| `dodopayments-api` | `https://mcp.dodopayments.com/mcp` | OAuth: a Dodo Payments consent page in the browser | Reading and changing real resources in your Dodo account |
|
|
16
16
|
|
|
17
17
|
## When to call which
|
|
18
18
|
|
|
@@ -43,13 +43,13 @@ Don't use the API server to answer "how does X work" questions. That's what `dod
|
|
|
43
43
|
|
|
44
44
|
The Dodo Payments MCP server uses **Code Mode**. Instead of one tool per endpoint, it exposes two tools:
|
|
45
45
|
|
|
46
|
-
1. **Docs search
|
|
46
|
+
1. **Docs search** (`search_docs`): query the API and SDK documentation.
|
|
47
47
|
2. **Code execution** (`execute`): write TypeScript against the `dodopayments` SDK. It runs in an isolated sandbox with no network or filesystem access, and whatever the code returns or prints comes back as the tool result.
|
|
48
48
|
|
|
49
49
|
What this means for you:
|
|
50
50
|
|
|
51
51
|
- Look at the tool list your client exposes for the exact tool names. Don't invent per-endpoint tool names like `create_product`; they don't exist in Code Mode.
|
|
52
|
-
- The
|
|
52
|
+
- The server authenticates every call with the user's OAuth sign-in. You never pass an API key or a token in tool parameters, and you shouldn't try to read one from inside the sandbox.
|
|
53
53
|
- Batch related calls into one script and return only what you need (IDs, statuses, counts), not whole objects. One script with 20 calls beats 20 round trips.
|
|
54
54
|
- Search docs (either server) for the SDK method shape before writing the script, then execute.
|
|
55
55
|
|
|
@@ -63,8 +63,8 @@ Typical read-only flow:
|
|
|
63
63
|
|
|
64
64
|
These are non-negotiable when the API server is connected.
|
|
65
65
|
|
|
66
|
-
1. **Default to test mode.**
|
|
67
|
-
2. **Know which mode you're in before any write.**
|
|
66
|
+
1. **Default to test mode.** The user picks the mode on the consent page when they sign in. During development, suggest test mode.
|
|
67
|
+
2. **Know which mode you're in before any write.** The tool configuration does not show the mode the user picked on the consent page, so **always ask the user to confirm test or live mode before the first write in a session**. A read can help you check: for example, if the user gives an ID, retrieving it succeeds only in the mode it was created in.
|
|
68
68
|
3. **Read before write.** Retrieve the resource first, show the user what will change, then act.
|
|
69
69
|
4. **Confirm every live mode write with the user**, naming the exact resource ID and the effect. This is mandatory for:
|
|
70
70
|
- refunds (full or partial),
|
|
@@ -72,71 +72,42 @@ These are non-negotiable when the API server is connected.
|
|
|
72
72
|
- anything that moves money or affects payouts,
|
|
73
73
|
- deleting or archiving products and discounts,
|
|
74
74
|
- changing or deleting webhook endpoints.
|
|
75
|
-
5. **Never print secrets.** Don't echo API keys, webhook signing keys, or full card or bank details into chat, logs, or files. Don't return them from `execute` scripts.
|
|
75
|
+
5. **Never print secrets.** Don't echo API keys, OAuth tokens, webhook signing keys, or full card or bank details into chat, logs, or files. Don't return them from `execute` scripts.
|
|
76
76
|
6. **Don't retry writes blindly.** If a create or refund call errors or times out, read the current state first (list refunds for the payment, fetch the subscription) before trying again, so you don't double-refund or create duplicates.
|
|
77
|
-
7. **Least privilege.**
|
|
77
|
+
7. **Least privilege.** On the consent page, the user grants only the permissions the task needs. For inspection-only work, suggest read permissions only.
|
|
78
78
|
|
|
79
79
|
## Authentication
|
|
80
80
|
|
|
81
|
-
|
|
81
|
+
The API server signs in with OAuth. No step asks for an API key.
|
|
82
82
|
|
|
83
|
-
The plugin points at `https://mcp.dodopayments.com/mcp`. The first
|
|
83
|
+
The plugin points at `https://mcp.dodopayments.com/mcp`. The first tool call opens a Dodo Payments consent page in the browser. The user signs in and picks the business, the mode (test or live) and the permissions to grant, then you retry the call. The client stores the token, so later sessions don't ask again until it expires or is revoked.
|
|
84
|
+
|
|
85
|
+
To review or revoke access, the user opens the Dodo Payments dashboard at **Settings > Connected Apps**. To switch to another business or mode, the user signs out of the server in the client and signs in again.
|
|
84
86
|
|
|
85
87
|
Both servers speak Streamable HTTP, so clients connect to the URL directly (no bridge process). Client setup, if the user is wiring it up by hand:
|
|
86
88
|
|
|
87
89
|
- **Claude Code**: `claude mcp add --transport http dodopayments-api https://mcp.dodopayments.com/mcp`
|
|
88
|
-
- **Cursor
|
|
90
|
+
- **Cursor** (`.cursor/mcp.json`): `{"mcpServers": {"dodopayments-api": {"url": "https://mcp.dodopayments.com/mcp"}}}`
|
|
91
|
+
- **Other `.mcp.json` clients**: `{"mcpServers": {"dodopayments-api": {"type": "http", "url": "https://mcp.dodopayments.com/mcp"}}}`
|
|
89
92
|
- **VS Code** (`.vscode/mcp.json` uses a top-level `servers` key): `{"servers": {"dodopayments-api": {"type": "http", "url": "https://mcp.dodopayments.com/mcp"}}}`
|
|
90
|
-
- **Codex CLI**: `codex mcp add dodopayments-api --url https://mcp.dodopayments.com/mcp`, then `codex mcp login dodopayments-api`
|
|
93
|
+
- **Codex CLI**: `codex mcp add dodopayments-api --url https://mcp.dodopayments.com/mcp`, then `codex mcp login dodopayments-api`. In `~/.codex/config.toml` this is a `[mcp_servers.dodopayments-api]` table with `url = "https://mcp.dodopayments.com/mcp"`.
|
|
94
|
+
- **OpenCode** (`opencode.json`): `{"mcp": {"dodopayments-api": {"type": "remote", "url": "https://mcp.dodopayments.com/mcp"}}}`, then `opencode mcp auth dodopayments-api`
|
|
91
95
|
- **Claude.ai**: Settings, Connectors, Add Custom Connector, paste the URL.
|
|
92
96
|
|
|
93
97
|
`dodo-knowledge` is configured the same way with `https://knowledge.dodopayments.com/mcp` and needs no sign-in.
|
|
94
98
|
|
|
95
|
-
For a client that cannot dial Streamable HTTP or run MCP OAuth itself, the `mcp-remote` bridge still works as a fallback: run `npx -y mcp-remote@latest https://mcp.dodopayments.com/mcp` as a stdio server.
|
|
96
|
-
|
|
97
|
-
### Local stdio server
|
|
98
|
-
|
|
99
|
-
Run the server on the user's machine with an API key:
|
|
100
|
-
|
|
101
|
-
```json
|
|
102
|
-
{
|
|
103
|
-
"mcpServers": {
|
|
104
|
-
"dodopayments_api": {
|
|
105
|
-
"command": "npx",
|
|
106
|
-
"args": ["-y", "dodopayments-mcp@latest"],
|
|
107
|
-
"env": {
|
|
108
|
-
"DODO_PAYMENTS_API_KEY": "dodo_test_...",
|
|
109
|
-
"DODO_PAYMENTS_WEBHOOK_KEY": "your_webhook_key",
|
|
110
|
-
"DODO_PAYMENTS_ENVIRONMENT": "test_mode"
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
| Variable | Required | Notes |
|
|
118
|
-
|----------|----------|-------|
|
|
119
|
-
| `DODO_PAYMENTS_API_KEY` | Yes | From the dashboard, Developer, API Keys |
|
|
120
|
-
| `DODO_PAYMENTS_WEBHOOK_KEY` | No | Webhook signing key |
|
|
121
|
-
| `DODO_PAYMENTS_ENVIRONMENT` | No | `test_mode` or `live_mode`; defaults to `live_mode` |
|
|
122
|
-
|
|
123
|
-
The local `execute` tool needs Deno on `PATH` (Deno 2.8 or earlier for now) and works on macOS and Linux only. On Windows, use WSL2 or the remote server. Docs search still works without Deno.
|
|
124
|
-
|
|
125
|
-
Tell the user to keep the key in their client config or environment, never in a committed file.
|
|
99
|
+
For a client that cannot dial Streamable HTTP or run MCP OAuth itself, the `mcp-remote` bridge still works as a fallback: run `npx -y mcp-remote@latest https://mcp.dodopayments.com/mcp` as a stdio server. It opens the same consent page.
|
|
126
100
|
|
|
127
101
|
## Troubleshooting
|
|
128
102
|
|
|
129
103
|
**"Needs authentication" or 401 from the remote server**
|
|
130
|
-
The OAuth sign-in hasn't happened or
|
|
104
|
+
The OAuth sign-in hasn't happened, has expired, or was revoked in Connected Apps. Ask the user to complete the consent page and retry. If it keeps failing, sign out and back in from the client's MCP menu (for example `/mcp` in Claude Code, `codex mcp login`), then restart the client. Clients that still use the older `mcp-remote` bridge cache tokens in `~/.mcp-auth`; clearing that folder forces a fresh sign-in.
|
|
131
105
|
|
|
132
|
-
**
|
|
133
|
-
The
|
|
106
|
+
**A 403 or permission error on one call while other calls work**
|
|
107
|
+
The permissions granted on the consent page don't cover that call, for example a refund without `refunds:write`. Ask the user to sign out of the server, sign in again, and grant the missing permission.
|
|
134
108
|
|
|
135
109
|
**Empty lists or "not found" for an ID the user just gave you**
|
|
136
|
-
You're probably in the wrong mode. Test mode and live mode data are fully separate. Confirm which mode the ID came from before concluding it doesn't exist.
|
|
137
|
-
|
|
138
|
-
**`execute` errors locally but docs search works**
|
|
139
|
-
Deno is missing, too new, or you're on Windows. See the local server notes above.
|
|
110
|
+
You're probably in the wrong mode. Test mode and live mode data are fully separate. Confirm which mode the ID came from before concluding it doesn't exist. To change the mode, the user signs in again and picks the other mode on the consent page.
|
|
140
111
|
|
|
141
112
|
**Tool execution failures**
|
|
142
113
|
Read the API error in the result; it usually names the bad field. Re-check the method shape with `dodo-knowledge`, then fix the script. You can also have the user reproduce the call with curl against `https://test.dodopayments.com` to rule out the MCP layer.
|
|
@@ -138,11 +138,14 @@ This immediately schedules the renewal. If you used the subscription-renewal-fai
|
|
|
138
138
|
The CLI ships separately from the SDKs:
|
|
139
139
|
|
|
140
140
|
```bash
|
|
141
|
-
npm
|
|
142
|
-
dodo login
|
|
141
|
+
npm i -g dodopayments-cli # browser sign-in needs v3.7.0 or later
|
|
142
|
+
dodo login # sign in with the browser
|
|
143
|
+
dodo whoami # show the stored sign-in
|
|
143
144
|
```
|
|
144
145
|
|
|
145
|
-
|
|
146
|
+
Over SSH or with no browser, run `dodo login --device` in place of `dodo login`, and enter the code on another device. To sign out when you finish, run `dodo logout all`.
|
|
147
|
+
|
|
148
|
+
`dodo login` opens a Dodo Payments consent page: pick the business, mode and permissions. No step asks you to paste an API key. To review or revoke the CLI's access, open the dashboard at **Settings > Connected Apps**.
|
|
146
149
|
|
|
147
150
|
### Listen for webhooks locally
|
|
148
151
|
|
|
@@ -154,7 +157,7 @@ This forwards real test-mode events to your local URL over an outbound relay. It
|
|
|
154
157
|
|
|
155
158
|
Two constraints to know before running it:
|
|
156
159
|
|
|
157
|
-
- **
|
|
160
|
+
- **Test mode only.** The listen flow needs a test-mode sign-in. Live mode is not supported.
|
|
158
161
|
- **The URL argument is required in direct mode.** Bare `dodo wh listen` only works inside the interactive TUI as `/wh listen`, which opens a wizard.
|
|
159
162
|
|
|
160
163
|
Events arriving this way carry valid signatures, so verify them normally with `webhooks.unwrap()`.
|
|
@@ -16,7 +16,7 @@ Forward real test-mode events to localhost:
|
|
|
16
16
|
dodo wh listen http://localhost:3000/webhook
|
|
17
17
|
```
|
|
18
18
|
|
|
19
|
-
This creates a test webhook, opens a WebSocket relay, and forwards events with the original `webhook-id`/`webhook-signature`/`webhook-timestamp` headers to your local URL. Requires a test-mode
|
|
19
|
+
This creates a test webhook, opens a WebSocket relay, and forwards events with the original `webhook-id`/`webhook-signature`/`webhook-timestamp` headers to your local URL. Requires a test-mode sign-in with `dodo login` (`dodo login --device` over SSH). The relay and CLI parse and **re-serialize** the JSON body, so if it differs byte-for-byte from the original (for example number formatting), signature verification fails even though the headers are intact - that is a relay artifact, not a bug in your verifier. The URL argument is required in direct mode — bare `dodo wh listen` only works as `/wh listen` inside the TUI.
|
|
20
20
|
|
|
21
21
|
### CLI: Unsigned mock events
|
|
22
22
|
|