opedd-mcp 0.12.10 → 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 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 21 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.
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 21 tools to any AI assistant (some are conditional on env vars):
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 + per-article purchase + onboarding + rights signaling**
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
- | `search_passages` | **Paid per answer, or included in a monthly subscription.** Ask a question, get licensed passages that answer it, with citations. Per-question licences: charged once per publisher per question at that publisher's own price, 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–25). 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, pricing, or that it is not on Opedd yet |
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 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
- "OPEDD_BUYER_EMAIL": "you@yourcompany.com",
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
- "OPEDD_BUYER_EMAIL": "you@yourcompany.com",
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
- > "Purchase a human republication license for that article on my behalf."
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, show you the results, and—if you've pre-configured a payment method—can complete a purchase autonomously.
249
+ The assistant will call the appropriate Opedd tools and show you the results.
255
250
 
256
- ## Payment methods
251
+ ## Payment
257
252
 
258
- Purchases use **Stripe** by default (via `pm_...` payment method IDs). USDC on Tempo is also supported by the Opedd API — pass `payment: { method: 'usdc', tx_hash: '0x...' }` directly to `agent-purchase` if building a custom integration.
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, available licence types and prices; 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).",
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 4 canonical license types (ai_retrieval, ai_training, human_per_article, human_full_archive) " +
380
- "the publisher has opted into, plus the EU CDSM Article 4(3) opt-out posture (`tdm_reservation`). " +
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 " +
@@ -442,7 +386,7 @@ function buildTools(has) {
442
386
  if (has.buyerToken) {
443
387
  TOOLS.push({
444
388
  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 publication whose passages are returned, at that publication's own price. 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) and max_results (1-25, default 10). 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.",
389
+ 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
390
  inputSchema: {
447
391
  type: "object",
448
392
  required: ["query"],
@@ -463,7 +407,11 @@ function buildTools(has) {
463
407
  },
464
408
  max_results: {
465
409
  type: "number",
466
- description: "Optional. Passages to return, 1\u201325 (default 10).",
410
+ description: "Optional. Passages to return, 1\u201310 (default 5). Each distinct article among them is one charge.",
411
+ },
412
+ max_charge_cents: {
413
+ type: "number",
414
+ 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
415
  },
468
416
  buyer_token: {
469
417
  type: "string",
@@ -476,7 +424,7 @@ function buildTools(has) {
476
424
  name: "get_content",
477
425
  description: "Retrieve the full body of a licensed article using a buyer API token (opedd_buyer_live_* canonical; opedd_buyer_test_* for sandbox). " +
478
426
  "Requires OPEDD_BUYER_TOKEN env var (create one at opedd.com/licenses after purchasing). " +
479
- "Works for per-article Human republication licences and for licence orders: AI answers monthly and client display " +
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 " +
480
428
  "return full text. Your self-serve buyer API key reads articles under every order your account holds — no " +
481
429
  "separate order token is needed. AI answers pay-per-request (including the self-serve licence) does NOT " +
482
430
  "retrieve articles: it answers 403 SEARCH_ONLY_LICENCE \u2014 ask a question with search_passages instead. " +
@@ -699,8 +647,7 @@ function buildTools(has) {
699
647
  description: "List all licensable articles for the authenticated publisher (requires OPEDD_PUB_BEARER, or legacy OPEDD_API_KEY). " +
700
648
  "Returns articles with titles, descriptions, pricing, and sales statistics. " +
701
649
  "Set include_body=true to read back the STORED article text exactly as licensed buyers receive it " +
702
- "(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). " +
703
- "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).",
704
651
  inputSchema: {
705
652
  type: "object",
706
653
  properties: {
@@ -708,11 +655,6 @@ function buildTools(has) {
708
655
  type: "number",
709
656
  description: "Number of results (default: 20, max: 100; max 20 when include_body is true)",
710
657
  },
711
- type: {
712
- type: "string",
713
- enum: ["human", "ai"],
714
- description: "Filter by license type availability (ignored when include_body is true)",
715
- },
716
658
  offset: {
717
659
  type: "number",
718
660
  description: "Pagination offset (default: 0; ignored when include_body is true — use cursor)",
@@ -777,11 +719,10 @@ function buildTools(has) {
777
719
  }
778
720
  const read = (title) => ({ title, readOnlyHint: true, destructiveHint: false, idempotentHint: true, openWorldHint: false });
779
721
  export const TOOL_ANNOTATIONS = {
780
- lookup_content: read("Look up an article's licence and price"),
722
+ lookup_content: read("Look up how an article is licensed"),
781
723
  // Writes one request row (a repeat for the same email writes nothing): not read-only, idempotent.
782
724
  request_publication: { title: "Ask to be told when a publication is available", readOnlyHint: false, destructiveHint: false, idempotentHint: true, openWorldHint: false },
783
725
  search_content: read("Find who covers a topic (free, no text)"),
784
- purchase_license: { title: "Buy an article licence", readOnlyHint: false, destructiveHint: false, idempotentHint: false, openWorldHint: false },
785
726
  verify_license: read("Verify a licence key"),
786
727
  browse_registry: read("Browse the licence registry"),
787
728
  publisher_directory: read("List publishers"),
@@ -830,7 +771,7 @@ export const ALL_TOOLS = buildTools({
830
771
  // registry metadata agents never see at runtime. Exported so the hosted
831
772
  // gateway (opedd-mcp-gateway) serves the identical text.
832
773
  export const SERVER_INSTRUCTIONS = "Opedd is content licensing for the AI era, between expert publishers and AI products: discover, purchase, verify and " +
833
- "retrieve rights-cleared expert content — one verifiable license key per article, a public record on " +
774
+ "retrieve rights-cleared expert content — a verifiable licence for every use, a public record on " +
834
775
  "Tempo, and compliance artifacts (audit ledger, dossiers and signed attestations). Use it instead of " +
835
776
  "unlicensed scraping for RAG, AI search, and training corpora.\n\n" +
836
777
  `No credentials needed: ${NO_AUTH_TOOLS}.\n` +
@@ -932,42 +873,6 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
932
873
  const envelope = (await opeddFetch(creds, `/api?${params.toString()}`));
933
874
  return ok(envelope.data ?? envelope);
934
875
  }
935
- // ── purchase_license ───────────────────────────────────────────────────
936
- case "purchase_license": {
937
- const { article_url, article_id, license_type, buyer_email: argEmail, buyer_name, buyer_organization, intended_use, payment_method_id: argPm, } = args;
938
- if (!article_url && !article_id) {
939
- return err("Either article_url or article_id is required");
940
- }
941
- const termsAccepted = args.terms_accepted;
942
- if (termsAccepted !== true) {
943
- return err("terms_accepted must be true — confirm with the buyer that they accept the Opedd licence terms (opedd.com/terms) before purchasing.");
944
- }
945
- const buyerEmail = argEmail || creds.buyerEmail;
946
- if (!buyerEmail) {
947
- return err("buyer_email is required (or set the OPEDD_BUYER_EMAIL env var)");
948
- }
949
- const paymentMethodId = argPm || creds.paymentMethodId;
950
- if (!paymentMethodId) {
951
- return err("payment_method_id is required (or set the OPEDD_PAYMENT_METHOD_ID env var). " +
952
- "Get a Stripe payment method ID by saving a card at stripe.com/docs/api/payment_methods.");
953
- }
954
- const body = {
955
- license_type,
956
- buyer_email: buyerEmail,
957
- // Genuine assent moment: the agent asserted terms_accepted=true just now.
958
- terms_accepted_at: new Date().toISOString(),
959
- payment: { method: "stripe_pm", payment_method_id: paymentMethodId },
960
- ...(article_id ? { article_id } : { article_url }),
961
- ...(buyer_name ? { buyer_name } : {}),
962
- ...(buyer_organization ? { buyer_organization } : {}),
963
- ...(intended_use ? { intended_use } : {}),
964
- };
965
- const data = await opeddFetch(creds, "/agent-purchase", {
966
- method: "POST",
967
- body: JSON.stringify(body),
968
- });
969
- return ok(data);
970
- }
971
876
  // ── verify_license ─────────────────────────────────────────────────────
972
877
  case "verify_license": {
973
878
  const { license_key } = args;
@@ -993,7 +898,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
993
898
  }
994
899
  // ── get_content ────────────────────────────────────────────────────────
995
900
  case "search_passages": {
996
- const { query, buyer_token: argToken, publishers, published_after, published_before, max_results } = args;
901
+ const { query, buyer_token: argToken, publishers, published_after, published_before, max_results, max_charge_cents } = args;
997
902
  const q = (query ?? "").replace(/\s+/g, " ").trim();
998
903
  if (!q)
999
904
  return err("query is required");
@@ -1004,7 +909,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
1004
909
  const token = argToken || creds.buyerToken;
1005
910
  if (!token) {
1006
911
  return err("This needs an Opedd buyer key. Sign up at https://opedd.com/buyer/signup (about two minutes): " +
1007
- "new accounts start with up to 3 free answers, then each answer is billed at the publication's own price. " +
912
+ "new accounts start with up to 3 free answers, then each article an answer uses is billed at its publication's own price. " +
1008
913
  "Then pass the key as Authorization: Bearer <key> (hosted server https://mcp.opedd.com/mcp) or " +
1009
914
  "OPEDD_BUYER_TOKEN (local). To see what Opedd covers first, use search_content or publisher_directory (free, no key).");
1010
915
  }
@@ -1019,6 +924,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
1019
924
  ...(published_after !== undefined ? { published_after } : {}),
1020
925
  ...(published_before !== undefined ? { published_before } : {}),
1021
926
  ...(max_results !== undefined ? { max_results } : {}),
927
+ ...(max_charge_cents !== undefined ? { max_charge_cents } : {}),
1022
928
  }),
1023
929
  }));
1024
930
  return ok(envelope.data ?? envelope);
@@ -1261,7 +1167,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
1261
1167
  if (!creds.pubBearer && !creds.apiKey) {
1262
1168
  return credErr("A publisher key (opedd_sk_*) is required for this tool", "OPEDD_PUB_BEARER", HOW_PUB_BEARER);
1263
1169
  }
1264
- const { limit = 20, type, offset = 0, include_body, cursor, id } = args;
1170
+ const { limit = 20, offset = 0, include_body, cursor, id } = args;
1265
1171
  // include_body (2026-09-14): the OWNER read model — GET /publishers-content
1266
1172
  // returns the stored body for the key's own rows. Bodies are truncated
1267
1173
  // here to keep the assistant's context bounded; ?id= returns one in full.
@@ -1292,8 +1198,6 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
1292
1198
  const params = new URLSearchParams({ action: "articles" });
1293
1199
  params.set("limit", String(Math.min(Number(limit), 100)));
1294
1200
  params.set("offset", String(Number(offset)));
1295
- if (type)
1296
- params.set("type", type);
1297
1201
  const data = await opeddFetch(creds, `/api?${params.toString()}`);
1298
1202
  return ok(data);
1299
1203
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opedd-mcp",
3
- "version": "0.12.10",
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",
@@ -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": "^4.1.7"
51
+ "vitest": "^5.0.5"
52
52
  },
53
53
  "engines": {
54
54
  "node": ">=20"