opedd-mcp 0.12.8 → 0.12.9

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.
Files changed (2) hide show
  1. package/dist/index.js +21 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -53,6 +53,7 @@ async function opeddFetch(creds, path, options = {}) {
53
53
  // proxy must surface as "HTTP 502", not a JSON SyntaxError.
54
54
  if (!res.ok) {
55
55
  let msg = `HTTP ${res.status}`;
56
+ let details;
56
57
  try {
57
58
  const errBody = await res.json();
58
59
  // Backend envelope upgraded to structured errors ({ error: { code,
@@ -60,6 +61,8 @@ async function opeddFetch(creds, path, options = {}) {
60
61
  // object into Error() rendered "[object Object]" — every agent-facing
61
62
  // failure was unreadable (launch-gaps follow-on, 2026-07-17).
62
63
  const e = errBody?.error;
64
+ if (typeof e === "object" && e !== null)
65
+ details = e.details;
63
66
  msg =
64
67
  (typeof e === "object" && e !== null ? [e.code, e.message].filter(Boolean).join(": ") : e) ||
65
68
  errBody?.message ||
@@ -69,8 +72,9 @@ async function opeddFetch(creds, path, options = {}) {
69
72
  // non-JSON error body — keep the HTTP-status default
70
73
  }
71
74
  // The status rides on the error so a caller can treat one status as an
72
- // answer (lookup_content: 404 = not on Opedd yet) without parsing text.
73
- throw Object.assign(new Error(msg), { status: res.status });
75
+ // answer (lookup_content: 404 = not on Opedd yet) without parsing text;
76
+ // error.details rides too (lookup_content: the publication at that site).
77
+ throw Object.assign(new Error(msg), { status: res.status, details });
74
78
  }
75
79
  return await res.json();
76
80
  }
@@ -184,7 +188,7 @@ function buildTools(has) {
184
188
  const TOOLS = [
185
189
  {
186
190
  name: "lookup_content",
187
- description: "Looks up an article on Opedd by its web address. Returns the title, publication, available licence types and prices, or that it is not on Opedd yet (then request_publication records the request).",
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).",
188
192
  inputSchema: {
189
193
  type: "object",
190
194
  required: ["url"],
@@ -878,6 +882,20 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
878
882
  // servers on error rates, and the honest reply is "not on Opedd yet"
879
883
  // with a way to ask for it, never "coming soon".
880
884
  if (e.status === 404) {
885
+ // No article at this address, but the address is a publication on
886
+ // Opedd (its homepage, or a piece not imported yet): say so, and
887
+ // where to license it (2026-10-24). Agents that looked up a
888
+ // publication's homepage were told it was not on Opedd.
889
+ const details = e.details;
890
+ if (details?.on_opedd === true && details.publication) {
891
+ return ok({
892
+ on_opedd: true,
893
+ url,
894
+ publication: details.publication,
895
+ message: `There is no single article at this address, but ${details.publication.name ?? "this publication"} is on Opedd. ` +
896
+ "Its licences and prices are on its licensing page; use search_content or search_passages to find its articles.",
897
+ });
898
+ }
881
899
  return ok({
882
900
  on_opedd: false,
883
901
  url,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opedd-mcp",
3
- "version": "0.12.8",
3
+ "version": "0.12.9",
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",