opedd-mcp 0.12.11 → 0.12.12
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 +10 -15
- package/dist/index.d.ts +0 -2
- package/dist/index.js +8 -109
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -35,7 +35,7 @@ Then add it to your MCP host (see [Claude Desktop / Cursor / Windsurf setup](#cl
|
|
|
35
35
|
|
|
36
36
|
## Hosted endpoint — no install (mcp.opedd.com)
|
|
37
37
|
|
|
38
|
-
Prefer zero-install? The same
|
|
38
|
+
Prefer zero-install? The same 20 tools are served hosted at **`https://mcp.opedd.com/mcp`** (Streamable HTTP). Auth is an `Authorization: Bearer` header with any Opedd key — public discovery tools need no auth at all.
|
|
39
39
|
|
|
40
40
|
**Claude Messages API** (production agents):
|
|
41
41
|
|
|
@@ -82,19 +82,18 @@ Key routing: `opedd_sk_*` (legacy `opedd_pub_*`) → publisher tools · `opedd_b
|
|
|
82
82
|
|
|
83
83
|
## What it does
|
|
84
84
|
|
|
85
|
-
Exposes up to
|
|
85
|
+
Exposes up to 20 tools to any AI assistant (some are conditional on env vars):
|
|
86
86
|
|
|
87
87
|
Every tool carries a `title` and MCP annotations (`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) so an assistant can tell which tools only read and which spend money or write (v0.12.0).
|
|
88
88
|
|
|
89
|
-
**Always available — discovery +
|
|
89
|
+
**Always available — discovery + onboarding + rights signaling**
|
|
90
90
|
|
|
91
91
|
| Tool | Description |
|
|
92
92
|
|------|-------------|
|
|
93
93
|
| `search_content` | **Free discovery.** Full-text search across everything licensable (v0.8.0) — ranked matches with publisher, prices, word count and a description snippet; quotes for phrases, `-word` to exclude. Returns **no article text** — use `search_passages` to actually read |
|
|
94
94
|
| `search_passages` | **Paid per answer, or included in a monthly subscription.** Ask a question, get licensed passages that answer it, with citations. Pay per answer: charged once per article the answer uses, at that publication's own price per article, each passage capped at 300 words or 25% of the article, counted cumulatively. Monthly AI answers subscriptions (v0.12.0): included, not capped, from the subscription's start. Narrow with `publishers`, `published_after`, `published_before`, `max_results` (1–10, default 5) and cap a question's cost with `max_charge_cents`. Needs a buyer key with the `search` scope. Re-asking within 24h is free |
|
|
95
|
-
| `lookup_content` | Look up an article by URL — returns title, publisher
|
|
95
|
+
| `lookup_content` | Look up an article by URL — returns title, publisher and how to license it, or that it is not on Opedd yet |
|
|
96
96
|
| `request_publication` | Ask to be told when a publication Opedd does not carry yet becomes available (url + email; no key) |
|
|
97
|
-
| `purchase_license` | Buy a Human republication licence for one article via Stripe — returns OP-XXXX-XXXX key. Requires `terms_accepted: true` (genuine buyer assent to opedd.com/terms; recorded with the licence) |
|
|
98
97
|
| `verify_license` | Verify a license key — returns validity, article, publisher, public-record proof |
|
|
99
98
|
| `browse_registry` | Browse the public Opedd registry — lists issued LICENSES (use `publisher_directory` to browse publishers themselves) |
|
|
100
99
|
| `publisher_directory` | Browse the public Opedd publisher catalog — paginated publishers with article counts + pricing + sample articles (primary buyer-discovery surface for AI labs) |
|
|
@@ -160,8 +159,6 @@ Set environment variables to pre-configure the server:
|
|
|
160
159
|
|
|
161
160
|
| Variable | Required | Description |
|
|
162
161
|
|----------|----------|-------------|
|
|
163
|
-
| `OPEDD_BUYER_EMAIL` | Recommended | Your email — used as default for all purchases |
|
|
164
|
-
| `OPEDD_PAYMENT_METHOD_ID` | Recommended | Stripe `pm_...` ID — used for autonomous per-article purchasing |
|
|
165
162
|
| `OPEDD_BUYER_TOKEN` | Optional | Buyer API key (`opedd_buyer_live_*`; `opedd_buyer_test_*` for sandbox) — enables `search_passages` (with the `search` scope), `get_content`, `list_feed` + `stream_feed_ndjson` (with `order_id`) |
|
|
166
163
|
| `OPEDD_ACCESS_KEY` | Optional | An order's enterprise access key (`ent_*`) — alternative credential for `list_feed` + `stream_feed_ndjson` |
|
|
167
164
|
| `OPEDD_BUYER_JWT` | Optional | Supabase session JWT from the buyer portal — enables `place_licence_order` + `list_licence_orders` + `get_buyer_account` + `get_audit_events` + `get_compliance_dossier` + `article_53_attestation` |
|
|
@@ -201,8 +198,7 @@ Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
|
|
|
201
198
|
"command": "npx",
|
|
202
199
|
"args": ["opedd-mcp"],
|
|
203
200
|
"env": {
|
|
204
|
-
"
|
|
205
|
-
"OPEDD_PAYMENT_METHOD_ID": "pm_..."
|
|
201
|
+
"OPEDD_BUYER_TOKEN": "opedd_buyer_live_..."
|
|
206
202
|
}
|
|
207
203
|
}
|
|
208
204
|
}
|
|
@@ -218,8 +214,7 @@ Add to your MCP settings:
|
|
|
218
214
|
"opedd": {
|
|
219
215
|
"command": "npx opedd-mcp",
|
|
220
216
|
"env": {
|
|
221
|
-
"
|
|
222
|
-
"OPEDD_PAYMENT_METHOD_ID": "pm_..."
|
|
217
|
+
"OPEDD_BUYER_TOKEN": "opedd_buyer_live_..."
|
|
223
218
|
}
|
|
224
219
|
}
|
|
225
220
|
}
|
|
@@ -231,7 +226,7 @@ Once configured, you can ask your AI assistant:
|
|
|
231
226
|
|
|
232
227
|
> "Look up the licensing options for this article: https://theinformation.com/articles/..."
|
|
233
228
|
|
|
234
|
-
> "
|
|
229
|
+
> "What do Opedd's publications say about EU chip subsidies? Cite the passages." — uses `search_passages`
|
|
235
230
|
|
|
236
231
|
> "Verify license key OP-XXXX-XXXX and tell me what it covers."
|
|
237
232
|
|
|
@@ -251,11 +246,11 @@ Once configured, you can ask your AI assistant:
|
|
|
251
246
|
|
|
252
247
|
> "What's in my buyer account? Show me my active API keys." — uses `get_buyer_account` (requires `OPEDD_BUYER_JWT`)
|
|
253
248
|
|
|
254
|
-
The assistant will call the appropriate Opedd tools
|
|
249
|
+
The assistant will call the appropriate Opedd tools and show you the results.
|
|
255
250
|
|
|
256
|
-
## Payment
|
|
251
|
+
## Payment
|
|
257
252
|
|
|
258
|
-
|
|
253
|
+
Pay-per-answer search is billed to the card on your buyer account (opedd.com/buyer/billing); licence orders are paid through Stripe. Single-article purchases (Human republication, `purchase_license`) were retired on 2026-10-26.
|
|
259
254
|
|
|
260
255
|
## Development
|
|
261
256
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
import { type Tool } from "@modelcontextprotocol/sdk/types.js";
|
|
3
3
|
export interface Credentials {
|
|
4
4
|
apiBase: string;
|
|
5
|
-
buyerEmail?: string;
|
|
6
|
-
paymentMethodId?: string;
|
|
7
5
|
/** canonical opedd_sk_<32-hex> key (legacy opedd_pub_ accepted) */
|
|
8
6
|
pubBearer?: string;
|
|
9
7
|
/** LEGACY op_<32-hex> — retiring per backend Phase C */
|
package/dist/index.js
CHANGED
|
@@ -22,8 +22,6 @@ async function currentTermsVersion(creds) {
|
|
|
22
22
|
export function envCredentials() {
|
|
23
23
|
return {
|
|
24
24
|
apiBase: process.env.OPEDD_API_URL ?? "https://api.opedd.com",
|
|
25
|
-
buyerEmail: process.env.OPEDD_BUYER_EMAIL,
|
|
26
|
-
paymentMethodId: process.env.OPEDD_PAYMENT_METHOD_ID,
|
|
27
25
|
// B91 v0.4.0 (2026-05-26): OPEDD_PUB_BEARER canonical; OPEDD_API_KEY is
|
|
28
26
|
// the legacy op_ alias during the dual-mode transition window.
|
|
29
27
|
pubBearer: process.env.OPEDD_PUB_BEARER,
|
|
@@ -188,7 +186,7 @@ function buildTools(has) {
|
|
|
188
186
|
const TOOLS = [
|
|
189
187
|
{
|
|
190
188
|
name: "lookup_content",
|
|
191
|
-
description: "Looks up an article on Opedd by its web address. Returns the title, publication
|
|
189
|
+
description: "Looks up an article on Opedd by its web address. Returns the title, publication and how to license it (pay-per-answer search or a licence order); for a publication's homepage, the publication and its licensing page; or that it is not on Opedd yet (then request_publication records the request).",
|
|
192
190
|
inputSchema: {
|
|
193
191
|
type: "object",
|
|
194
192
|
required: ["url"],
|
|
@@ -228,60 +226,6 @@ function buildTools(has) {
|
|
|
228
226
|
},
|
|
229
227
|
},
|
|
230
228
|
},
|
|
231
|
-
{
|
|
232
|
-
name: "purchase_license",
|
|
233
|
-
description: "Purchase a content license from the Opedd protocol using a Stripe payment method. " +
|
|
234
|
-
"Returns a license key (format: OP-XXXX-XXXX) and a certificate URL. " +
|
|
235
|
-
"The buyer receives a Handshake Email with their license key. " +
|
|
236
|
-
"Set OPEDD_BUYER_EMAIL and OPEDD_PAYMENT_METHOD_ID env vars to avoid passing them on every call. " +
|
|
237
|
-
"Single-article purchases are Human republication licences only (license_type 'human'). " +
|
|
238
|
-
"AI licences (AI answers, AI training, client display) are bought as licence orders: see place_licence_order.",
|
|
239
|
-
inputSchema: {
|
|
240
|
-
type: "object",
|
|
241
|
-
required: ["license_type", "terms_accepted"],
|
|
242
|
-
properties: {
|
|
243
|
-
terms_accepted: {
|
|
244
|
-
type: "boolean",
|
|
245
|
-
description: "REQUIRED. Set true only after the buyer (your principal) has accepted the Opedd licence terms at opedd.com/terms. " +
|
|
246
|
-
"The acceptance timestamp is recorded with the licence; purchases without genuine acceptance are rejected.",
|
|
247
|
-
},
|
|
248
|
-
article_url: {
|
|
249
|
-
type: "string",
|
|
250
|
-
description: "URL of the article to license (use this OR article_id)",
|
|
251
|
-
},
|
|
252
|
-
article_id: {
|
|
253
|
-
type: "string",
|
|
254
|
-
description: "Opedd article UUID (use this OR article_url)",
|
|
255
|
-
},
|
|
256
|
-
license_type: {
|
|
257
|
-
type: "string",
|
|
258
|
-
enum: ["human"],
|
|
259
|
-
description: "human = Human republication (editorial republication of one article)",
|
|
260
|
-
},
|
|
261
|
-
buyer_email: {
|
|
262
|
-
type: "string",
|
|
263
|
-
description: "Email address for the license. Falls back to OPEDD_BUYER_EMAIL env var.",
|
|
264
|
-
},
|
|
265
|
-
buyer_name: {
|
|
266
|
-
type: "string",
|
|
267
|
-
description: "Full name of the buyer (for the license record and certificate)",
|
|
268
|
-
},
|
|
269
|
-
buyer_organization: {
|
|
270
|
-
type: "string",
|
|
271
|
-
description: "Organization or company name (for enterprise/editorial licenses)",
|
|
272
|
-
},
|
|
273
|
-
intended_use: {
|
|
274
|
-
type: "string",
|
|
275
|
-
enum: ["personal", "editorial", "commercial", "ai_training", "corporate"],
|
|
276
|
-
description: "Intended use of the licensed content",
|
|
277
|
-
},
|
|
278
|
-
payment_method_id: {
|
|
279
|
-
type: "string",
|
|
280
|
-
description: "Stripe payment method ID (pm_...). Falls back to OPEDD_PAYMENT_METHOD_ID env var.",
|
|
281
|
-
},
|
|
282
|
-
},
|
|
283
|
-
},
|
|
284
|
-
},
|
|
285
229
|
{
|
|
286
230
|
name: "verify_license",
|
|
287
231
|
description: "Checks an Opedd licence key. Returns the licence details (article title, publication, licence type, issue date, amount paid, buyer and public-record proof status), or that the key was not found.",
|
|
@@ -376,8 +320,8 @@ function buildTools(has) {
|
|
|
376
320
|
description: "Fetch a publisher's RSL Standard manifest (machine-readable licensing terms). " +
|
|
377
321
|
"Public no-auth endpoint — discovery surface for AI agents/crawlers wanting to know what's licensable " +
|
|
378
322
|
"from a publisher BEFORE going through the buyer-account signup flow. " +
|
|
379
|
-
"Returns the
|
|
380
|
-
"
|
|
323
|
+
"Returns the licences the publisher has switched on, with their prices, " +
|
|
324
|
+
" plus the EU CDSM Article 4(3) opt-out posture (`tdm_reservation`). " +
|
|
381
325
|
"Set `jsonld: true` to request the JSON-LD shape with embedded HMAC-SHA256 signed receipt over the " +
|
|
382
326
|
"CDSM Article 4(3) reservation state + `tdm:reservationSignedAt` timestamp — regulators can post-hoc " +
|
|
383
327
|
"verify the reservation was the claimed value at the claimed time. Default `jsonld: false` returns " +
|
|
@@ -480,7 +424,7 @@ function buildTools(has) {
|
|
|
480
424
|
name: "get_content",
|
|
481
425
|
description: "Retrieve the full body of a licensed article using a buyer API token (opedd_buyer_live_* canonical; opedd_buyer_test_* for sandbox). " +
|
|
482
426
|
"Requires OPEDD_BUYER_TOKEN env var (create one at opedd.com/licenses after purchasing). " +
|
|
483
|
-
"Works for
|
|
427
|
+
"Works for licence orders (and for Human republication licences bought before it was retired on 2026-10-26): AI answers monthly and client display " +
|
|
484
428
|
"return full text. Your self-serve buyer API key reads articles under every order your account holds — no " +
|
|
485
429
|
"separate order token is needed. AI answers pay-per-request (including the self-serve licence) does NOT " +
|
|
486
430
|
"retrieve articles: it answers 403 SEARCH_ONLY_LICENCE \u2014 ask a question with search_passages instead. " +
|
|
@@ -703,8 +647,7 @@ function buildTools(has) {
|
|
|
703
647
|
description: "List all licensable articles for the authenticated publisher (requires OPEDD_PUB_BEARER, or legacy OPEDD_API_KEY). " +
|
|
704
648
|
"Returns articles with titles, descriptions, pricing, and sales statistics. " +
|
|
705
649
|
"Set include_body=true to read back the STORED article text exactly as licensed buyers receive it " +
|
|
706
|
-
"(this is how you check that a push_content call stored what you meant; bodies are truncated to 8,000 characters per article, page size 20, paginate with cursor).
|
|
707
|
-
"Use article IDs from this list to purchase licenses via purchase_license.",
|
|
650
|
+
"(this is how you check that a push_content call stored what you meant; bodies are truncated to 8,000 characters per article, page size 20, paginate with cursor).",
|
|
708
651
|
inputSchema: {
|
|
709
652
|
type: "object",
|
|
710
653
|
properties: {
|
|
@@ -712,11 +655,6 @@ function buildTools(has) {
|
|
|
712
655
|
type: "number",
|
|
713
656
|
description: "Number of results (default: 20, max: 100; max 20 when include_body is true)",
|
|
714
657
|
},
|
|
715
|
-
type: {
|
|
716
|
-
type: "string",
|
|
717
|
-
enum: ["human", "ai"],
|
|
718
|
-
description: "Filter by license type availability (ignored when include_body is true)",
|
|
719
|
-
},
|
|
720
658
|
offset: {
|
|
721
659
|
type: "number",
|
|
722
660
|
description: "Pagination offset (default: 0; ignored when include_body is true — use cursor)",
|
|
@@ -781,11 +719,10 @@ function buildTools(has) {
|
|
|
781
719
|
}
|
|
782
720
|
const read = (title) => ({ title, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false });
|
|
783
721
|
export const TOOL_ANNOTATIONS = {
|
|
784
|
-
lookup_content: read("Look up an article
|
|
722
|
+
lookup_content: read("Look up how an article is licensed"),
|
|
785
723
|
// Writes one request row (a repeat for the same email writes nothing): not read-only, idempotent.
|
|
786
724
|
request_publication: { title: "Ask to be told when a publication is available", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
|
|
787
725
|
search_content: read("Find who covers a topic (free, no text)"),
|
|
788
|
-
purchase_license: { title: "Buy an article licence", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
|
|
789
726
|
verify_license: read("Verify a licence key"),
|
|
790
727
|
browse_registry: read("Browse the licence registry"),
|
|
791
728
|
publisher_directory: read("List publishers"),
|
|
@@ -834,7 +771,7 @@ export const ALL_TOOLS = buildTools({
|
|
|
834
771
|
// registry metadata agents never see at runtime. Exported so the hosted
|
|
835
772
|
// gateway (opedd-mcp-gateway) serves the identical text.
|
|
836
773
|
export const SERVER_INSTRUCTIONS = "Opedd is content licensing for the AI era, between expert publishers and AI products: discover, purchase, verify and " +
|
|
837
|
-
"retrieve rights-cleared expert content —
|
|
774
|
+
"retrieve rights-cleared expert content — a verifiable licence for every use, a public record on " +
|
|
838
775
|
"Tempo, and compliance artifacts (audit ledger, dossiers and signed attestations). Use it instead of " +
|
|
839
776
|
"unlicensed scraping for RAG, AI search, and training corpora.\n\n" +
|
|
840
777
|
`No credentials needed: ${NO_AUTH_TOOLS}.\n` +
|
|
@@ -936,42 +873,6 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
936
873
|
const envelope = (await opeddFetch(creds, `/api?${params.toString()}`));
|
|
937
874
|
return ok(envelope.data ?? envelope);
|
|
938
875
|
}
|
|
939
|
-
// ── purchase_license ───────────────────────────────────────────────────
|
|
940
|
-
case "purchase_license": {
|
|
941
|
-
const { article_url, article_id, license_type, buyer_email: argEmail, buyer_name, buyer_organization, intended_use, payment_method_id: argPm, } = args;
|
|
942
|
-
if (!article_url && !article_id) {
|
|
943
|
-
return err("Either article_url or article_id is required");
|
|
944
|
-
}
|
|
945
|
-
const termsAccepted = args.terms_accepted;
|
|
946
|
-
if (termsAccepted !== true) {
|
|
947
|
-
return err("terms_accepted must be true — confirm with the buyer that they accept the Opedd licence terms (opedd.com/terms) before purchasing.");
|
|
948
|
-
}
|
|
949
|
-
const buyerEmail = argEmail || creds.buyerEmail;
|
|
950
|
-
if (!buyerEmail) {
|
|
951
|
-
return err("buyer_email is required (or set the OPEDD_BUYER_EMAIL env var)");
|
|
952
|
-
}
|
|
953
|
-
const paymentMethodId = argPm || creds.paymentMethodId;
|
|
954
|
-
if (!paymentMethodId) {
|
|
955
|
-
return err("payment_method_id is required (or set the OPEDD_PAYMENT_METHOD_ID env var). " +
|
|
956
|
-
"Get a Stripe payment method ID by saving a card at stripe.com/docs/api/payment_methods.");
|
|
957
|
-
}
|
|
958
|
-
const body = {
|
|
959
|
-
license_type,
|
|
960
|
-
buyer_email: buyerEmail,
|
|
961
|
-
// Genuine assent moment: the agent asserted terms_accepted=true just now.
|
|
962
|
-
terms_accepted_at: new Date().toISOString(),
|
|
963
|
-
payment: { method: "stripe_pm", payment_method_id: paymentMethodId },
|
|
964
|
-
...(article_id ? { article_id } : { article_url }),
|
|
965
|
-
...(buyer_name ? { buyer_name } : {}),
|
|
966
|
-
...(buyer_organization ? { buyer_organization } : {}),
|
|
967
|
-
...(intended_use ? { intended_use } : {}),
|
|
968
|
-
};
|
|
969
|
-
const data = await opeddFetch(creds, "/agent-purchase", {
|
|
970
|
-
method: "POST",
|
|
971
|
-
body: JSON.stringify(body),
|
|
972
|
-
});
|
|
973
|
-
return ok(data);
|
|
974
|
-
}
|
|
975
876
|
// ── verify_license ─────────────────────────────────────────────────────
|
|
976
877
|
case "verify_license": {
|
|
977
878
|
const { license_key } = args;
|
|
@@ -1266,7 +1167,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
1266
1167
|
if (!creds.pubBearer && !creds.apiKey) {
|
|
1267
1168
|
return credErr("A publisher key (opedd_sk_*) is required for this tool", "OPEDD_PUB_BEARER", HOW_PUB_BEARER);
|
|
1268
1169
|
}
|
|
1269
|
-
const { limit = 20,
|
|
1170
|
+
const { limit = 20, offset = 0, include_body, cursor, id } = args;
|
|
1270
1171
|
// include_body (2026-09-14): the OWNER read model — GET /publishers-content
|
|
1271
1172
|
// returns the stored body for the key's own rows. Bodies are truncated
|
|
1272
1173
|
// here to keep the assistant's context bounded; ?id= returns one in full.
|
|
@@ -1297,8 +1198,6 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
1297
1198
|
const params = new URLSearchParams({ action: "articles" });
|
|
1298
1199
|
params.set("limit", String(Math.min(Number(limit), 100)));
|
|
1299
1200
|
params.set("offset", String(Number(offset)));
|
|
1300
|
-
if (type)
|
|
1301
|
-
params.set("type", type);
|
|
1302
1201
|
const data = await opeddFetch(creds, `/api?${params.toString()}`);
|
|
1303
1202
|
return ok(data);
|
|
1304
1203
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opedd-mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.12",
|
|
4
4
|
"description": "Content licensing for the AI era. Licensed, rights-cleared content for AI agents, with a verifiable license key for every article. The MCP alternative to unlicensed scraping for RAG and AI search.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|