opedd-mcp 0.10.0 → 0.11.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
@@ -95,7 +95,7 @@ Exposes up to 19 tools to any AI assistant (some are conditional on env vars):
95
95
  | `verify_license` | Verify a license key — returns validity, article, publisher, blockchain proof |
96
96
  | `browse_registry` | Browse the public Opedd registry — lists issued LICENSES (use `publisher_directory` to browse publishers themselves) |
97
97
  | `publisher_directory` | Browse the public Opedd publisher catalog — paginated publishers with article counts + pricing + sample articles (primary buyer-discovery surface for AI labs) |
98
- | `place_licence_order` | Place a licence order for one or more publishers: AI answers (`monthly` full text, or `metered` pay-per-request snippets ≤300 words / 25%), AI training (`one_time`, back catalogue), client display (`monthly` × end clients). Each publisher is its own Schedule at its own price; returns the order, lines, `unavailable` publishers and `hosted_invoice_url`. Needs `OPEDD_BUYER_JWT` and `terms_accepted: true` |
98
+ | `place_licence_order` | Place a licence order for one or more publishers: AI answers (`monthly` full text, or `metered` pay-per-request snippets ≤300 words / 25%), Full catalogue (`archive`, `one_time`: everything published up to the order date, kept permanently, no AI training), AI training (`one_time`, back catalogue), client display (`monthly` × end clients). Optional `include_archive: true` on a monthly AI answers order adds each publisher's Full catalogue for complete access. Each publisher is its own Schedule at its own price; returns the order, lines, `unavailable` publishers and `hosted_invoice_url`. Needs `OPEDD_BUYER_JWT` and `terms_accepted: true` |
99
99
  | `rsl_get` | Fetch a publisher's RSL Standard manifest — public discovery surface; `jsonld: true` returns CDSM Article 4(3) signed receipt (Phase 12 W1.1) |
100
100
  | `detect_platform` | Detect the content platform behind a URL — returns suggested onboarding workflow for Substack / Beehiiv / Ghost / Medium / Brevo / custom (Phase 12 W3.1) |
101
101
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import { type Tool } from "@modelcontextprotocol/sdk/types.js";
3
- export declare const CURRENT_MSA_VERSION = "master-services-agreement-2026-07-22b";
4
3
  export interface Credentials {
5
4
  apiBase: string;
6
5
  buyerEmail?: string;
package/dist/index.js CHANGED
@@ -6,11 +6,19 @@ import { pathToFileURL } from "node:url";
6
6
  import { initTelemetry, captureToolCall, shutdownTelemetry } from "./telemetry.js";
7
7
  import { SERVER_VERSION } from "./version.js";
8
8
  // ─── Configuration ────────────────────────────────────────────────────────────
9
- // Current Opedd Master Services Agreement version label. MUST match
10
- // opedd-backend supabase/functions/_shared/msa-version.ts CURRENT_MSA_VERSION
11
- // (the backend rejects superseded labels). On an MSA version bump, update this
12
- // constant and cut a new package release.
13
- export const CURRENT_MSA_VERSION = "master-services-agreement-2026-07-22b";
9
+ // The Buyer Master Agreement label is read from the API when an order is
10
+ // placed (GET /api?action=trust_facts -> agreements.enterprise_msa_current),
11
+ // never pinned here: a pinned label went stale when the agreement was
12
+ // republished, and the API refuses any label that is not the current one
13
+ // (409 NOT_CURRENT_VERSION), so every place_licence_order from 0.10.0 failed.
14
+ async function currentTermsVersion(creds) {
15
+ const facts = (await opeddFetch(creds, "/api?action=trust_facts"));
16
+ const label = facts?.data?.agreements?.enterprise_msa_current;
17
+ if (typeof label !== "string" || !label) {
18
+ throw new Error("Could not read the current Buyer Master Agreement from the API");
19
+ }
20
+ return label;
21
+ }
14
22
  export function envCredentials() {
15
23
  return {
16
24
  apiBase: process.env.OPEDD_API_URL ?? "https://api.opedd.com",
@@ -376,19 +384,28 @@ function buildTools(has) {
376
384
  description: "Place a licence order with Opedd for one or more publishers. One order = one licence and one billing mode; " +
377
385
  "each publisher becomes its own Schedule priced from that publisher's settings (publishers that do not offer it are " +
378
386
  "returned in `unavailable` and never charged). Licences: 'enterprise' (AI answers: 'monthly' full text per article, or " +
379
- "'metered' pay-per-request snippets of up to 300 words or 25% of the article), 'training' (AI training of the back " +
380
- "catalogue up to the order date: 'one_time', bulk export via stream_feed_ndjson), 'display' (client display: 'monthly', " +
381
- "quantity = number of end clients). Returns the order, its lines, the access key (works once paid) and " +
387
+ "'metered' pay-per-request snippets of up to 300 words or 25% of the article), 'archive' (Full catalogue: everything " +
388
+ "the publisher published up to the order date, kept permanently, not for AI training: 'one_time', full text in the feed), " +
389
+ "'training' (AI training of the back catalogue up to the order date: 'one_time', bulk export via stream_feed_ndjson), " +
390
+ "'display' (client display: 'monthly', quantity = number of end clients). A monthly AI answers subscription only covers " +
391
+ "articles published from the day it starts; set include_archive=true on a 'enterprise' + 'monthly' order to add each " +
392
+ "publisher's Full catalogue in the same order (complete access). Returns the order, its lines, the access key (works once paid) and " +
382
393
  "hosted_invoice_url — the buyer (your principal) pays there. Requires a buyer session (OPEDD_BUYER_JWT) and " +
383
394
  "terms_accepted=true after the buyer has accepted the Opedd Master Services Agreement (opedd.com/terms).",
384
395
  inputSchema: {
385
396
  type: "object",
386
397
  required: ["licence", "billing_mode", "publisher_ids", "terms_accepted"],
387
398
  properties: {
388
- licence: { type: "string", enum: ["enterprise", "training", "display"], description: "enterprise = AI answers, training = AI training, display = client display" },
389
- billing_mode: { type: "string", enum: ["monthly", "metered", "one_time"], description: "enterprise: monthly | metered; training: one_time; display: monthly" },
399
+ licence: { type: "string", enum: ["enterprise", "archive", "training", "display"], description: "enterprise = AI answers, archive = Full catalogue (everything published up to the order date, kept permanently, no AI training), training = AI training, display = client display" },
400
+ billing_mode: { type: "string", enum: ["monthly", "metered", "one_time"], description: "enterprise: monthly | metered; archive: one_time; training: one_time; display: monthly" },
390
401
  publisher_ids: { type: "array", items: { type: "string" }, description: "Publisher UUIDs (1-500; at most 18 for metered)" },
391
402
  quantity: { type: "number", description: "display only: number of end clients (1-500)" },
403
+ include_archive: {
404
+ type: "boolean",
405
+ description: "Optional, monthly AI answers only (licence 'enterprise' + billing_mode 'monthly'). true adds each publisher's " +
406
+ "Full catalogue to the same order: everything published before the order date, kept permanently, not for AI training. " +
407
+ "Publishers that do not sell their Full catalogue are returned in `unavailable`.",
408
+ },
392
409
  terms_accepted: {
393
410
  type: "boolean",
394
411
  description: "REQUIRED. Set true only after the buyer has accepted the Opedd Master Services Agreement at opedd.com/terms. " +
@@ -951,14 +968,24 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
951
968
  if (!creds.buyerJwt) {
952
969
  return credErr("A buyer session is required to place an order", "OPEDD_BUYER_JWT", HOW_BUYER_JWT);
953
970
  }
954
- const { licence, billing_mode, publisher_ids, quantity, terms_accepted } = args;
971
+ const { licence, billing_mode, publisher_ids, quantity, include_archive, terms_accepted } = args;
955
972
  if (!licence || !billing_mode)
956
973
  return err("licence and billing_mode are required");
974
+ if (include_archive !== undefined && typeof include_archive !== "boolean") {
975
+ return err("include_archive must be true or false");
976
+ }
977
+ // Same rule and wording as the API (opedd-backend
978
+ // _shared/licence-order-lines.ts parseOrderRequest): the Full catalogue
979
+ // is what a monthly AI answers subscription leaves out.
980
+ if (include_archive === true && !(licence === "enterprise" && billing_mode === "monthly")) {
981
+ return err("include_archive applies only to a monthly AI answers licence");
982
+ }
957
983
  if (!Array.isArray(publisher_ids) || publisher_ids.length === 0)
958
984
  return err("publisher_ids must be a non-empty array");
959
985
  if (terms_accepted !== true) {
960
- return err("terms_accepted must be true — confirm with the buyer that they accept the Opedd Master Services Agreement (opedd.com/terms) before ordering.");
986
+ return err("terms_accepted must be true — confirm with the buyer that they accept the Opedd Buyer Master Agreement and the Standard Licence Terms (opedd.com/licence-terms) before ordering.");
961
987
  }
988
+ const termsVersion = await currentTermsVersion(creds);
962
989
  const data = await opeddFetch(creds, "/enterprise-license", {
963
990
  method: "POST",
964
991
  headers: { Authorization: `Bearer ${creds.buyerJwt}` },
@@ -967,10 +994,10 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
967
994
  billing_mode,
968
995
  publisher_ids,
969
996
  ...(quantity !== undefined ? { quantity } : {}),
997
+ ...(include_archive === true ? { include_archive: true } : {}),
970
998
  // Genuine assent moment: the agent asserted terms_accepted=true just
971
- // now. On an MSA version bump this constant must be updated (new
972
- // package release) to match opedd-backend _shared/msa-version.ts.
973
- terms_version: CURRENT_MSA_VERSION,
999
+ // now, for the agreement currently in force.
1000
+ terms_version: termsVersion,
974
1001
  }),
975
1002
  });
976
1003
  return ok(data);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opedd-mcp",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "description": "Licensed, rights-cleared content for AI agents — verifiable license keys, on-chain proof, and EU AI Act attestation. The MCP alternative to unlicensed scraping for RAG and AI search.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",