opedd-mcp 0.6.13 → 0.6.14
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/dist/index.d.ts +1 -0
- package/dist/index.js +47 -9
- package/dist/telemetry.d.ts +1 -0
- package/dist/telemetry.js +25 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -27,5 +27,6 @@ type ToolResult = {
|
|
|
27
27
|
};
|
|
28
28
|
export declare const TOOLS: Tool[];
|
|
29
29
|
export declare const ALL_TOOLS: Tool[];
|
|
30
|
+
export declare const SERVER_INSTRUCTIONS: string;
|
|
30
31
|
export declare function dispatchTool(name: string, args: Record<string, unknown>, creds?: Credentials): Promise<ToolResult>;
|
|
31
32
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -118,6 +118,27 @@ function ok(data) {
|
|
|
118
118
|
function err(msg) {
|
|
119
119
|
return { content: [{ type: "text", text: `Error: ${msg}` }], isError: true };
|
|
120
120
|
}
|
|
121
|
+
// ─── Credential refusals are the conversion surface ──────────────────────────
|
|
122
|
+
// (2026-08-26) In the week before this landed, 19 distinct agents worldwide
|
|
123
|
+
// succeeded on browse_registry and then hit a credential gate whose entire
|
|
124
|
+
// message was "env var is required" — no next action, funnel over. The AUTH
|
|
125
|
+
// MODEL IS UNCHANGED by this block: same gates, same keys, nothing loosened.
|
|
126
|
+
// Only the refusal text changed: what's missing, how to supply it on BOTH
|
|
127
|
+
// channels (env var locally, Authorization header on the hosted gateway),
|
|
128
|
+
// where credentials come from, and which tools need none.
|
|
129
|
+
const NO_AUTH_TOOLS = "lookup_content, publisher_directory, verify_license, browse_registry, rsl_get, detect_platform";
|
|
130
|
+
function credErr(missing, envVar, howToGet) {
|
|
131
|
+
return err(`${missing} — none was provided. ` +
|
|
132
|
+
`Supply it as the ${envVar} env var (local/stdio install) or as an "Authorization: Bearer <value>" header (hosted gateway, https://mcp.opedd.com/mcp). ` +
|
|
133
|
+
`${howToGet} ` +
|
|
134
|
+
`These tools need no credentials at all: ${NO_AUTH_TOOLS}. Docs: https://docs.opedd.com`);
|
|
135
|
+
}
|
|
136
|
+
const HOW_BUYER_JWT = "Buyer signup is free and takes ~2 minutes: https://opedd.com/buyer/signup (an API key is issued instantly at signup). " +
|
|
137
|
+
"This tool authenticates with your buyer session JWT: sign in at https://opedd.com/buyer and use the Supabase session access token. " +
|
|
138
|
+
"Blocked? hello@opedd.com.";
|
|
139
|
+
const HOW_ACCESS_KEY = "Enterprise access keys (ent_*) are delivered when an enterprise licence is issued — start at https://opedd.com/enterprise " +
|
|
140
|
+
"or purchase programmatically with the purchase_enterprise_license tool.";
|
|
141
|
+
const HOW_PUB_BEARER = "Publisher keys (opedd_pub_*) come from the publisher dashboard: sign up free at https://opedd.com, then Settings → API keys.";
|
|
121
142
|
// ─── Tool definitions ─────────────────────────────────────────────────────────
|
|
122
143
|
function buildTools(has) {
|
|
123
144
|
const TOOLS = [
|
|
@@ -670,7 +691,24 @@ export const ALL_TOOLS = buildTools({
|
|
|
670
691
|
buyerToken: true, accessKey: true, buyerJwt: true, pubBearer: true,
|
|
671
692
|
});
|
|
672
693
|
// ─── MCP Server ───────────────────────────────────────────────────────────────
|
|
673
|
-
|
|
694
|
+
// ─── Handshake instructions ──────────────────────────────────────────────────
|
|
695
|
+
// The MCP `instructions` field is the one string every connecting agent reads
|
|
696
|
+
// at initialize — it was empty until 2026-08-26 while the pitch lived only in
|
|
697
|
+
// registry metadata agents never see at runtime. Exported so the hosted
|
|
698
|
+
// gateway (opedd-mcp-gateway) serves the identical text.
|
|
699
|
+
export const SERVER_INSTRUCTIONS = "Opedd is the licensing rail between expert publishers and AI products: discover, purchase, verify and " +
|
|
700
|
+
"retrieve rights-cleared expert content — one verifiable license key per article, Tempo on-chain " +
|
|
701
|
+
"attestation, and EU AI Act Article 53 compliance artifacts (audit ledger + dossiers). Use it instead of " +
|
|
702
|
+
"unlicensed scraping for RAG, AI search, and training corpora.\n\n" +
|
|
703
|
+
`No credentials needed: ${NO_AUTH_TOOLS}.\n` +
|
|
704
|
+
"Buyer tools (purchase, account, audit/compliance): free buyer signup at https://opedd.com/buyer/signup " +
|
|
705
|
+
"(~2 min; an API key is issued instantly). Publisher tools (content push): free publisher signup at " +
|
|
706
|
+
"https://opedd.com, key under Settings → API keys.\n" +
|
|
707
|
+
"Supply credentials as env vars (local/stdio) or an Authorization: Bearer header (hosted gateway, " +
|
|
708
|
+
"https://mcp.opedd.com/mcp).\n" +
|
|
709
|
+
"EU CDSM Art. 4(3) / TDM-reservation queries: rsl_get. Compliance evidence: get_compliance_dossier. " +
|
|
710
|
+
"Docs: https://docs.opedd.com";
|
|
711
|
+
const server = new Server({ name: "opedd-mcp", version: SERVER_VERSION }, { capabilities: { tools: {} }, instructions: SERVER_INSTRUCTIONS });
|
|
674
712
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS }));
|
|
675
713
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
676
714
|
// Anonymous usage telemetry — captures only the tool name, duration, and
|
|
@@ -850,7 +888,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
850
888
|
// ── list_feed (Phase 10 + 11) ──────────────────────────────────────────
|
|
851
889
|
case "list_feed": {
|
|
852
890
|
if (!creds.accessKey) {
|
|
853
|
-
return
|
|
891
|
+
return credErr("An enterprise access key (ent_*) is required for this tool", "OPEDD_ACCESS_KEY", HOW_ACCESS_KEY);
|
|
854
892
|
}
|
|
855
893
|
const { since, cursor, limit = 50 } = args;
|
|
856
894
|
const params = new URLSearchParams({
|
|
@@ -871,7 +909,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
871
909
|
// ── stream_feed_ndjson (Phase 11 M3) ───────────────────────────────────
|
|
872
910
|
case "stream_feed_ndjson": {
|
|
873
911
|
if (!creds.accessKey) {
|
|
874
|
-
return
|
|
912
|
+
return credErr("An enterprise access key (ent_*) is required for this tool", "OPEDD_ACCESS_KEY", HOW_ACCESS_KEY);
|
|
875
913
|
}
|
|
876
914
|
const { since, cursor, limit = 200 } = args;
|
|
877
915
|
const params = new URLSearchParams({
|
|
@@ -892,7 +930,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
892
930
|
// ── get_audit_events (Phase 9.x + 10 M5 attestation) ───────────────────
|
|
893
931
|
case "get_audit_events": {
|
|
894
932
|
if (!creds.buyerJwt) {
|
|
895
|
-
return
|
|
933
|
+
return credErr("A buyer session JWT is required for this tool", "OPEDD_BUYER_JWT", HOW_BUYER_JWT);
|
|
896
934
|
}
|
|
897
935
|
const { from, to, event_type, cursor, limit = 50 } = args;
|
|
898
936
|
const params = new URLSearchParams({
|
|
@@ -914,7 +952,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
914
952
|
// ── get_buyer_account (buyer profile + masked key list) ────────────────
|
|
915
953
|
case "get_buyer_account": {
|
|
916
954
|
if (!creds.buyerJwt) {
|
|
917
|
-
return
|
|
955
|
+
return credErr("A buyer session JWT is required for this tool", "OPEDD_BUYER_JWT", HOW_BUYER_JWT);
|
|
918
956
|
}
|
|
919
957
|
const data = await opeddFetch(creds, "/buyer-account", {
|
|
920
958
|
headers: { Authorization: `Bearer ${creds.buyerJwt}` },
|
|
@@ -924,7 +962,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
924
962
|
// ── article_53_attestation (Phase 12 Wave 1 W1.4) ──────────────────────
|
|
925
963
|
case "article_53_attestation": {
|
|
926
964
|
if (!creds.buyerJwt) {
|
|
927
|
-
return
|
|
965
|
+
return credErr("A buyer session JWT is required for this tool", "OPEDD_BUYER_JWT", HOW_BUYER_JWT);
|
|
928
966
|
}
|
|
929
967
|
const { license_id, content_id, window_start, window_end } = args;
|
|
930
968
|
if (!license_id)
|
|
@@ -947,7 +985,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
947
985
|
// ── get_compliance_dossier (Phase 11 M4) ───────────────────────────────
|
|
948
986
|
case "get_compliance_dossier": {
|
|
949
987
|
if (!creds.buyerJwt) {
|
|
950
|
-
return
|
|
988
|
+
return credErr("A buyer session JWT is required for this tool", "OPEDD_BUYER_JWT", HOW_BUYER_JWT);
|
|
951
989
|
}
|
|
952
990
|
const { from, to, cursor } = args;
|
|
953
991
|
if (!from)
|
|
@@ -969,7 +1007,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
969
1007
|
// ── list_publisher_content ─────────────────────────────────────────────
|
|
970
1008
|
case "list_publisher_content": {
|
|
971
1009
|
if (!creds.pubBearer && !creds.apiKey) {
|
|
972
|
-
return
|
|
1010
|
+
return credErr("A publisher key (opedd_pub_*) is required for this tool", "OPEDD_PUB_BEARER", HOW_PUB_BEARER);
|
|
973
1011
|
}
|
|
974
1012
|
const { limit = 20, type, offset = 0 } = args;
|
|
975
1013
|
const params = new URLSearchParams({ action: "articles" });
|
|
@@ -983,7 +1021,7 @@ export async function dispatchTool(name, args, creds = ENV_CREDS) {
|
|
|
983
1021
|
// ── push_content ───────────────────────────────────────────────────────
|
|
984
1022
|
case "push_content": {
|
|
985
1023
|
if (!creds.pubBearer && !creds.apiKey) {
|
|
986
|
-
return
|
|
1024
|
+
return credErr("A publisher key (opedd_pub_*) is required for this tool", "OPEDD_PUB_BEARER", HOW_PUB_BEARER);
|
|
987
1025
|
}
|
|
988
1026
|
const { articles } = args;
|
|
989
1027
|
if (!Array.isArray(articles) || articles.length === 0) {
|
package/dist/telemetry.d.ts
CHANGED
|
@@ -8,4 +8,5 @@ export declare function isTelemetryEnabled(): boolean;
|
|
|
8
8
|
export declare function toolCallProperties(tool: string, durationMs: number, ok: boolean, extra?: Record<string, string | number | boolean>): Record<string, string | number | boolean>;
|
|
9
9
|
export declare function initTelemetry(): void;
|
|
10
10
|
export declare function captureToolCall(tool: string, durationMs: number, ok: boolean, extra?: Record<string, string | number | boolean>): void;
|
|
11
|
+
export declare function captureClientConnect(clientName: string, clientVersion: string, extra?: Record<string, string | number | boolean>): void;
|
|
11
12
|
export declare function shutdownTelemetry(): Promise<void>;
|
package/dist/telemetry.js
CHANGED
|
@@ -87,6 +87,31 @@ extra) {
|
|
|
87
87
|
/* telemetry must never affect a tool call */
|
|
88
88
|
}
|
|
89
89
|
}
|
|
90
|
+
// Client-framework identification (2026-08-26). The MCP initialize request
|
|
91
|
+
// carries the client's SELF-DECLARED name/version (e.g. "claude-desktop",
|
|
92
|
+
// "cursor", a company's custom agent) — the only identity signal the
|
|
93
|
+
// protocol offers, and we were discarding it while trying to identify
|
|
94
|
+
// callers by city. Same privacy posture as tool calls: these two strings
|
|
95
|
+
// plus the caller-supplied extra (geo/channel) only — no params, PII, keys.
|
|
96
|
+
export function captureClientConnect(clientName, clientVersion, extra) {
|
|
97
|
+
if (!client)
|
|
98
|
+
return;
|
|
99
|
+
try {
|
|
100
|
+
client.capture({
|
|
101
|
+
distinctId: sessionId,
|
|
102
|
+
event: "mcp_client_connect",
|
|
103
|
+
properties: {
|
|
104
|
+
...(extra ?? {}),
|
|
105
|
+
client_name: clientName.slice(0, 120),
|
|
106
|
+
client_version: clientVersion.slice(0, 40),
|
|
107
|
+
server_version: SERVER_VERSION,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
catch {
|
|
112
|
+
/* telemetry must never affect a request */
|
|
113
|
+
}
|
|
114
|
+
}
|
|
90
115
|
export async function shutdownTelemetry() {
|
|
91
116
|
const c = client;
|
|
92
117
|
client = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "opedd-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.14",
|
|
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",
|