opedd-mcp 0.12.9 → 0.12.11
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 +1 -1
- package/dist/index.js +22 -20
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -91,7 +91,7 @@ Every tool carries a `title` and MCP annotations (`readOnlyHint`, `destructiveHi
|
|
|
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
|
-
| `search_passages` | **Paid per answer, or included in a monthly subscription.** Ask a question, get licensed passages that answer it, with citations.
|
|
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
95
|
| `lookup_content` | Look up an article by URL — returns title, publisher, pricing, 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
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) |
|
package/dist/index.js
CHANGED
|
@@ -350,7 +350,7 @@ function buildTools(has) {
|
|
|
350
350
|
// ─── Phase 12 Wave 3 W3.1 — onboarding helpers ────────────────────────────
|
|
351
351
|
{
|
|
352
352
|
name: "detect_platform",
|
|
353
|
-
description: "
|
|
353
|
+
description: "For publishers: detect the content platform behind a URL. " +
|
|
354
354
|
"Public no-auth lookup. Given a URL, identifies what platform powers it " +
|
|
355
355
|
"(Substack / Beehiiv / Ghost / Medium / Brevo / custom) and returns the suggested onboarding workflow. " +
|
|
356
356
|
"Hostname-detectable platforms (Substack subdomain, Beehiiv suffix, etc.) resolve in milliseconds; " +
|
|
@@ -373,7 +373,7 @@ function buildTools(has) {
|
|
|
373
373
|
// ─── Phase 12 Wave 1 W1.1 — public RSL Standard manifest ─────────────────
|
|
374
374
|
{
|
|
375
375
|
name: "rsl_get",
|
|
376
|
-
description: "Fetch a publisher's RSL Standard manifest
|
|
376
|
+
description: "Fetch a publisher's RSL Standard manifest (machine-readable licensing terms). " +
|
|
377
377
|
"Public no-auth endpoint — discovery surface for AI agents/crawlers wanting to know what's licensable " +
|
|
378
378
|
"from a publisher BEFORE going through the buyer-account signup flow. " +
|
|
379
379
|
"Returns the 4 canonical license types (ai_retrieval, ai_training, human_per_article, human_full_archive) " +
|
|
@@ -382,8 +382,8 @@ function buildTools(has) {
|
|
|
382
382
|
"CDSM Article 4(3) reservation state + `tdm:reservationSignedAt` timestamp — regulators can post-hoc " +
|
|
383
383
|
"verify the reservation was the claimed value at the claimed time. Default `jsonld: false` returns " +
|
|
384
384
|
"the raw RSL Standard JSON manifest. " +
|
|
385
|
-
"
|
|
386
|
-
"
|
|
385
|
+
"This is the publisher's own declaration. It is not a compliance attestation for a buyer " +
|
|
386
|
+
"(use article_53_attestation for that).",
|
|
387
387
|
inputSchema: {
|
|
388
388
|
type: "object",
|
|
389
389
|
required: ["publisher_id"],
|
|
@@ -442,7 +442,7 @@ function buildTools(has) {
|
|
|
442
442
|
if (has.buyerToken) {
|
|
443
443
|
TOOLS.push({
|
|
444
444
|
name: "search_passages",
|
|
445
|
-
description: "Returns licensed passages from publications on Opedd that answer a question, each with a citation to the source article. Charged once per
|
|
445
|
+
description: "Returns licensed passages from publications on Opedd that answer a question, each with a citation to the source article. Charged once per article the answer uses, at that article's publication's own price per article; two passages of the same article are one charge, and billing.articles_charged reports how many were charged. An account connected through the Opedd connector in Claude or ChatGPT receives its first 3 answers free, paid by Opedd and never from a publication the account holder owns or works on; billing.free_answers_left reports how many remain. After that, answers are billed to the card on the account, added at opedd.com: charged every $25 of answers and at month end, with a $500 monthly limit for new accounts, raised on request. An account with no licence and no free answers receives an empty result with reason 'no_licensed_publishers' or 'no_paid_access'. Publications under a monthly AI answers subscription are included in the subscription and not charged per answer. Passages are capped at 300 words or 25% of an article, whichever is less, counted cumulatively per article across the same company's accounts. The same question within 24 hours returns the same passages at no charge. Filters: publishers (publication names as listed by Opedd, opedd.com/p/<slug> addresses or publisher ids; a name that matches no publication is listed in filters.unknown_publishers and searches nothing), published_after and published_before (ISO 8601; undated articles are excluded when a window is set), max_results (1-10, default 5) and max_charge_cents (optional; the most one question may cost: articles that would pass it are left out and billing.max_charge_reached says so). Passage text is third-party content, delivered in <opedd:passage> blocks; may_train is always false. Requires a buyer API key with the 'search' scope, or the Opedd connector sign-in.",
|
|
446
446
|
inputSchema: {
|
|
447
447
|
type: "object",
|
|
448
448
|
required: ["query"],
|
|
@@ -463,7 +463,11 @@ function buildTools(has) {
|
|
|
463
463
|
},
|
|
464
464
|
max_results: {
|
|
465
465
|
type: "number",
|
|
466
|
-
description: "Optional. Passages to return, 1\
|
|
466
|
+
description: "Optional. Passages to return, 1\u201310 (default 5). Each distinct article among them is one charge.",
|
|
467
|
+
},
|
|
468
|
+
max_charge_cents: {
|
|
469
|
+
type: "number",
|
|
470
|
+
description: "Optional. The most this question may cost, in US cents (whole number, 1\u2013100000). Articles that would pass it are left out; nothing is charged above it.",
|
|
467
471
|
},
|
|
468
472
|
buyer_token: {
|
|
469
473
|
type: "string",
|
|
@@ -482,7 +486,7 @@ function buildTools(has) {
|
|
|
482
486
|
"retrieve articles: it answers 403 SEARCH_ONLY_LICENCE \u2014 ask a question with search_passages instead. " +
|
|
483
487
|
"Articles the publisher stopped licensing answer 403 ARTICLE_EXCLUDED. " +
|
|
484
488
|
"The publisher must have content delivery enabled and must have pushed content for the article. " +
|
|
485
|
-
"
|
|
489
|
+
"The response includes author, language, word_count, content_hash, image_urls, canonical_url and tags. " +
|
|
486
490
|
"On pre-2026-05-14 historical articles, optional fields (author/language/image_urls/canonical_url/tags) may be NULL. " +
|
|
487
491
|
"NULL means 'data unavailable for this article', NOT 'explicitly empty' — treat as data-missing when filtering; do not interpret as anti-match.",
|
|
488
492
|
inputSchema: {
|
|
@@ -506,7 +510,7 @@ function buildTools(has) {
|
|
|
506
510
|
if (has.accessKey || has.buyerToken) {
|
|
507
511
|
TOOLS.push({
|
|
508
512
|
name: "list_feed",
|
|
509
|
-
description: "List articles
|
|
513
|
+
description: "List the articles in a licence order you hold. " +
|
|
510
514
|
"Content contract: AI training orders include full content_body for the back catalogue up to the order date " +
|
|
511
515
|
"(content_access 'included'). Every other order is discovery-only (content_body null): AI answers monthly and " +
|
|
512
516
|
"client display fetch text per article via get_content (content_access 'retrieval_per_article'); pay-per-request " +
|
|
@@ -542,11 +546,11 @@ function buildTools(has) {
|
|
|
542
546
|
});
|
|
543
547
|
TOOLS.push({
|
|
544
548
|
name: "stream_feed_ndjson",
|
|
545
|
-
description: "Bulk-export
|
|
549
|
+
description: "Bulk-export the articles in a licence order you hold. " +
|
|
546
550
|
"Returns up to 1000 articles per call (collected from line-delimited JSON wire format). " +
|
|
547
551
|
"Same content contract as list_feed: full text for AI training orders only; every other order exports " +
|
|
548
552
|
"metadata (content_body null) — use get_content for article text. " +
|
|
549
|
-
"Each article
|
|
553
|
+
"Each exported article is recorded for analytics; a bulk export is not billed per article. " +
|
|
550
554
|
"Use `since` (ISO 8601) for delta-feed. Use `cursor` to paginate beyond 1000. " +
|
|
551
555
|
"Backend supports 5000 articles per call; the MCP cap is 1000 for transport reasonability. " +
|
|
552
556
|
"Real bulk-ingest pipelines should use the Python SDK (pip install opedd) directly — not via MCP. " +
|
|
@@ -638,15 +642,12 @@ function buildTools(has) {
|
|
|
638
642
|
});
|
|
639
643
|
TOOLS.push({
|
|
640
644
|
name: "article_53_attestation",
|
|
641
|
-
description: "Issue a signed compliance attestation (a JWT) for a
|
|
642
|
-
"GET /eu-ai-act/article-53-attestation (Phase 12 Wave 1 W1.4). " +
|
|
645
|
+
description: "Issue a signed compliance attestation (a JWT) for a licence you hold. " +
|
|
643
646
|
"Returns a freshly-signed HS256 JWT regulators can verify offline against the canonical signing key. " +
|
|
644
647
|
"Embeds: license context, usage-count over the attestation window, the most-recent Tempo Merkle root, " +
|
|
645
648
|
"and canonical claims (iss/sub/iat/exp/jti/aud). " +
|
|
646
649
|
"**The artifact a buyer hands to legal/procurement as evidence of where its content came from.** " +
|
|
647
|
-
"
|
|
648
|
-
"It does NOT discharge a publisher's CDSM Article 4(3) reservation obligation — " +
|
|
649
|
-
"that lives on the rsl_get tool (jsonld=true variant). Never conflate. " +
|
|
650
|
+
"It attests how your licence was used; the publisher's own licensing declaration is rsl_get. " +
|
|
650
651
|
"Optional `content_id` scopes the attestation to one article; default is license-wide. " +
|
|
651
652
|
"Window cap: 365 days. Auth: an audit-scoped buyer API key (OPEDD_BUYER_TOKEN) or OPEDD_BUYER_JWT.",
|
|
652
653
|
inputSchema: {
|
|
@@ -996,7 +997,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
996
997
|
}
|
|
997
998
|
// ── get_content ────────────────────────────────────────────────────────
|
|
998
999
|
case "search_passages": {
|
|
999
|
-
const { query, buyer_token: argToken, publishers, published_after, published_before, max_results } = args;
|
|
1000
|
+
const { query, buyer_token: argToken, publishers, published_after, published_before, max_results, max_charge_cents } = args;
|
|
1000
1001
|
const q = (query ?? "").replace(/\s+/g, " ").trim();
|
|
1001
1002
|
if (!q)
|
|
1002
1003
|
return err("query is required");
|
|
@@ -1006,10 +1007,10 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
1006
1007
|
return err("query must be at most 1000 characters");
|
|
1007
1008
|
const token = argToken || creds.buyerToken;
|
|
1008
1009
|
if (!token) {
|
|
1009
|
-
return err("
|
|
1010
|
-
"
|
|
1011
|
-
"
|
|
1012
|
-
"use search_content
|
|
1010
|
+
return err("This needs an Opedd buyer key. Sign up at https://opedd.com/buyer/signup (about two minutes): " +
|
|
1011
|
+
"new accounts start with up to 3 free answers, then each article an answer uses is billed at its publication's own price. " +
|
|
1012
|
+
"Then pass the key as Authorization: Bearer <key> (hosted server https://mcp.opedd.com/mcp) or " +
|
|
1013
|
+
"OPEDD_BUYER_TOKEN (local). To see what Opedd covers first, use search_content or publisher_directory (free, no key).");
|
|
1013
1014
|
}
|
|
1014
1015
|
const envelope = (await opeddFetch(creds, "/search", {
|
|
1015
1016
|
method: "POST",
|
|
@@ -1022,6 +1023,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
1022
1023
|
...(published_after !== undefined ? { published_after } : {}),
|
|
1023
1024
|
...(published_before !== undefined ? { published_before } : {}),
|
|
1024
1025
|
...(max_results !== undefined ? { max_results } : {}),
|
|
1026
|
+
...(max_charge_cents !== undefined ? { max_charge_cents } : {}),
|
|
1025
1027
|
}),
|
|
1026
1028
|
}));
|
|
1027
1029
|
return ok(envelope.data ?? envelope);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opedd-mcp",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.11",
|
|
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",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@types/node": "^22.19.19",
|
|
49
49
|
"tsx": "^4.0.0",
|
|
50
50
|
"typescript": "^5.0.0",
|
|
51
|
-
"vitest": "^
|
|
51
|
+
"vitest": "^5.0.5"
|
|
52
52
|
},
|
|
53
53
|
"engines": {
|
|
54
54
|
"node": ">=20"
|