@refkit/mcp 0.6.0 → 0.7.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 +3 -1
- package/dist/{chunk-DQHNPSDF.js → chunk-WVJJN6XK.js} +65 -33
- package/dist/chunk-WVJJN6XK.js.map +1 -0
- package/dist/cli.d.ts +6 -1
- package/dist/cli.js +21 -4
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +21 -20
- package/dist/chunk-DQHNPSDF.js.map +0 -1
package/README.md
CHANGED
|
@@ -10,7 +10,7 @@ Point any MCP client at:
|
|
|
10
10
|
npx -y @refkit/mcp
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
It boots with the keyless sources (Met, Art Institute of Chicago, Wikimedia Commons, Openverse + audio, Project Gutenberg, PoetryDB) and auto-adds any BYOK source whose key is in the environment. Each key is read as a unified `REFKIT_<PROVIDER>_KEY` name first, falling back to the provider's legacy name (both are honored indefinitely):
|
|
13
|
+
It boots with the keyless sources (Met, Art Institute of Chicago, Wikimedia Commons, Openverse + audio, Project Gutenberg, PoetryDB, Nailbook — Japanese nail-art, discovery-class `license: 'unknown'`, best queried with Japanese tag words) and auto-adds any BYOK source whose key is in the environment. Each key is read as a unified `REFKIT_<PROVIDER>_KEY` name first, falling back to the provider's legacy name (both are honored indefinitely):
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
16
|
REFKIT_UNSPLASH_KEY=… REFKIT_PEXELS_KEY=… REFKIT_PIXABAY_KEY=… REFKIT_FLICKR_KEY=… REFKIT_SMITHSONIAN_KEY=… REFKIT_BRAVE_KEY=… npx -y @refkit/mcp
|
|
@@ -19,6 +19,8 @@ REFKIT_UNSPLASH_KEY=… REFKIT_PEXELS_KEY=… REFKIT_PIXABAY_KEY=… REFKIT_FLIC
|
|
|
19
19
|
UNSPLASH_KEY=… PEXELS_KEY=… PIXABAY_KEY=… FLICKR_KEY=… SI_KEY=… BRAVE_TOKEN=… npx -y @refkit/mcp
|
|
20
20
|
```
|
|
21
21
|
|
|
22
|
+
If your MCP client clamps tool-output strings, `REFKIT_MAX_CURSOR_SEEN` shrinks the load-more cursor: it caps how many already-returned keys `nextCursor` remembers (default 500 ≈ 2.7k chars; `REFKIT_MAX_CURSOR_SEEN=200` ≈ 1.1k). A lower cap only risks re-showing results from that many batches ago on very deep pagination.
|
|
23
|
+
|
|
22
24
|
Example MCP client config:
|
|
23
25
|
|
|
24
26
|
```json
|
|
@@ -6,6 +6,7 @@ import { z } from "zod";
|
|
|
6
6
|
import { LICENSE_IDS, INTENTS, evaluateUse, buildAttribution, ccVersionFor, lexicalReranker } from "@refkit/core";
|
|
7
7
|
var MODALITIES = ["image", "video", "audio", "text"];
|
|
8
8
|
var ORIENTATIONS = ["landscape", "portrait", "square"];
|
|
9
|
+
var BASE_MEDIA_KINDS = ["photo", "illustration", "vector", "film", "animation"];
|
|
9
10
|
var SEARCH_CONTROL_KEYS = [
|
|
10
11
|
"orientation",
|
|
11
12
|
"color",
|
|
@@ -31,33 +32,35 @@ var filtersSchema = z.object({
|
|
|
31
32
|
language: z.string().optional()
|
|
32
33
|
});
|
|
33
34
|
var searchControlKeySchema = z.enum(SEARCH_CONTROL_KEYS);
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
35
|
+
function buildSearchControlsSchema(kindValues) {
|
|
36
|
+
return z.object({
|
|
37
|
+
orientation: z.enum(ORIENTATIONS).optional(),
|
|
38
|
+
color: z.string().optional(),
|
|
39
|
+
language: z.string().optional(),
|
|
40
|
+
sort: z.enum(["relevance", "latest", "popular", "interesting"]).optional(),
|
|
41
|
+
safety: z.enum(["strict", "moderate", "off"]).optional(),
|
|
42
|
+
license: z.object({
|
|
43
|
+
commercial: z.boolean().optional(),
|
|
44
|
+
modification: z.boolean().optional(),
|
|
45
|
+
allowUnknown: z.boolean().optional()
|
|
46
|
+
}).optional(),
|
|
47
|
+
media: z.object({
|
|
48
|
+
kind: z.enum(kindValues).optional(),
|
|
49
|
+
size: z.enum(["small", "medium", "large"]).optional(),
|
|
50
|
+
minWidth: z.number().int().nonnegative().optional(),
|
|
51
|
+
minHeight: z.number().int().nonnegative().optional(),
|
|
52
|
+
duration: z.enum(["short", "medium", "long"]).optional()
|
|
53
|
+
}).optional(),
|
|
54
|
+
creator: z.object({
|
|
55
|
+
id: z.string().optional(),
|
|
56
|
+
name: z.string().optional()
|
|
57
|
+
}).optional(),
|
|
58
|
+
text: z.object({
|
|
59
|
+
copyright: z.enum(["public-domain", "copyrighted", "any"]).optional()
|
|
60
|
+
}).optional(),
|
|
61
|
+
page: z.number().int().positive().optional()
|
|
62
|
+
});
|
|
63
|
+
}
|
|
61
64
|
var providerOptionValueSchema = z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]);
|
|
62
65
|
var providerOptionsSchema = z.record(z.string(), z.record(z.string(), providerOptionValueSchema));
|
|
63
66
|
var VERSION = (() => {
|
|
@@ -72,6 +75,7 @@ function toAgentRef(r, assessment) {
|
|
|
72
75
|
id: r.id,
|
|
73
76
|
title: r.title,
|
|
74
77
|
modality: r.modality,
|
|
78
|
+
kind: r.kind,
|
|
75
79
|
provider: r.source.providerId,
|
|
76
80
|
canonicalUrl: r.canonicalUrl,
|
|
77
81
|
license: r.rights.license,
|
|
@@ -93,6 +97,7 @@ var agentRefSchema = z.object({
|
|
|
93
97
|
id: z.string(),
|
|
94
98
|
title: z.string().optional(),
|
|
95
99
|
modality: z.string(),
|
|
100
|
+
kind: z.string().optional().describe("fine-grained resource kind, e.g. photo / texture / ebook"),
|
|
96
101
|
provider: z.string(),
|
|
97
102
|
canonicalUrl: z.string(),
|
|
98
103
|
license: z.string(),
|
|
@@ -121,7 +126,7 @@ var searchMetaSchema = z.object({
|
|
|
121
126
|
returned: z.number().optional(),
|
|
122
127
|
accepted: z.number().optional(),
|
|
123
128
|
rejected: z.number().optional(),
|
|
124
|
-
reason: z.enum(["unsupported-modality"]).optional(),
|
|
129
|
+
reason: z.enum(["unsupported-modality", "unsupported-kind", "not-selected"]).optional(),
|
|
125
130
|
error: z.string().optional(),
|
|
126
131
|
latencyMs: z.number().optional(),
|
|
127
132
|
cached: z.boolean().optional()
|
|
@@ -137,14 +142,27 @@ var searchMetaSchema = z.object({
|
|
|
137
142
|
});
|
|
138
143
|
function createRefkitMcpServer(refkit) {
|
|
139
144
|
const server = new McpServer({ name: "refkit", version: VERSION });
|
|
145
|
+
const enabledSourceIds = refkit.providers.map((p) => p.id);
|
|
146
|
+
const registered = refkit.providers;
|
|
147
|
+
const modalityValues = [...new Set(registered.flatMap((p) => p.modalities))];
|
|
148
|
+
const kindValues = [.../* @__PURE__ */ new Set([...BASE_MEDIA_KINDS, ...registered.flatMap((p) => p.kinds ?? [])])];
|
|
149
|
+
const sourceList = registered.map((p) => {
|
|
150
|
+
const kinds = p.kinds?.length ? `\xB7${p.kinds.join(",")}` : "";
|
|
151
|
+
const desc = p.description ? `: ${p.description}` : "";
|
|
152
|
+
return `- ${p.id} (${p.modalities.join("/")}${kinds})${desc}`;
|
|
153
|
+
}).join("\n");
|
|
154
|
+
const searchControlsSchema = buildSearchControlsSchema(kindValues);
|
|
140
155
|
server.registerTool(
|
|
141
156
|
"search_references",
|
|
142
157
|
{
|
|
143
158
|
title: "Search creative references",
|
|
144
|
-
description: "Search license-normalized reference material (image / video / audio / text) across the configured sources. Every result carries a license id + canonical source link. Pass `intent` to annotate each result with a use-verdict (may I use this, is attribution required) WITHOUT filtering; pass `gateFor` to instead return only results whose license allows that intent. Results are references, not rights clearance \u2014 not legal advice
|
|
159
|
+
description: "Search license-normalized reference material (image / video / audio / text) across the configured sources. Every result carries a license id + canonical source link. Pass `intent` to annotate each result with a use-verdict (may I use this, is attribution required) WITHOUT filtering; pass `gateFor` to instead return only results whose license allows that intent. Results are references, not rights clearance \u2014 not legal advice.\n\nConfigured sources:\n" + sourceList,
|
|
145
160
|
inputSchema: {
|
|
146
161
|
query: z.string().describe('what to search for, e.g. "cyberpunk alley at night"'),
|
|
147
|
-
modalities: z.array(z.enum(
|
|
162
|
+
modalities: z.array(z.enum(modalityValues)).optional().describe('default ["image"]'),
|
|
163
|
+
sources: z.array(z.string()).optional().describe(
|
|
164
|
+
`restrict the search to specific sources by id (omit to search every configured source \u2014 see "Configured sources" in this tool description). Use to scope a search-engine operator (e.g. "site:example.com") to a web-discovery source without affecting other sources' queries.`
|
|
165
|
+
),
|
|
148
166
|
filters: filtersSchema.optional().describe("compatibility alias for controls.orientation, controls.color, and controls.language"),
|
|
149
167
|
controls: searchControlsSchema.optional().describe("provider-neutral search controls; providers translate supported controls and report ignored controls in explain metadata"),
|
|
150
168
|
providerOptions: providerOptionsSchema.optional().describe("provider-specific search controls keyed by provider id; each provider whitelists supported keys"),
|
|
@@ -161,10 +179,11 @@ function createRefkitMcpServer(refkit) {
|
|
|
161
179
|
meta: searchMetaSchema.optional()
|
|
162
180
|
}
|
|
163
181
|
},
|
|
164
|
-
async ({ query, modalities, filters, controls, providerOptions, explain, limit, cursor, rerank, intent, gateFor }) => {
|
|
182
|
+
async ({ query, modalities, filters, controls, providerOptions, explain, limit, cursor, rerank, intent, gateFor, sources }) => {
|
|
165
183
|
const searchInput = {
|
|
166
184
|
query,
|
|
167
185
|
modalities: modalities ?? ["image"],
|
|
186
|
+
sources,
|
|
168
187
|
filters,
|
|
169
188
|
controls,
|
|
170
189
|
providerOptions,
|
|
@@ -173,7 +192,20 @@ function createRefkitMcpServer(refkit) {
|
|
|
173
192
|
...rerank ? { rerank: lexicalReranker() } : {},
|
|
174
193
|
gateFor
|
|
175
194
|
};
|
|
176
|
-
|
|
195
|
+
let result;
|
|
196
|
+
try {
|
|
197
|
+
result = await refkit.searchWithMeta(searchInput);
|
|
198
|
+
} catch (err) {
|
|
199
|
+
if (sources && sources.length > 0 && !(err instanceof AggregateError)) {
|
|
200
|
+
const available = enabledSourceIds.join(", ") || "(none)";
|
|
201
|
+
const detail = err instanceof Error ? err.message : String(err);
|
|
202
|
+
return {
|
|
203
|
+
isError: true,
|
|
204
|
+
content: [{ type: "text", text: `${detail} Enabled source ids: ${available}.` }]
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
throw err;
|
|
208
|
+
}
|
|
177
209
|
const refs = result.references;
|
|
178
210
|
const assessIntent = intent ?? gateFor;
|
|
179
211
|
const references = refs.map(
|
|
@@ -274,4 +306,4 @@ export {
|
|
|
274
306
|
createRefkitMcpServer,
|
|
275
307
|
serveStdio
|
|
276
308
|
};
|
|
277
|
-
//# sourceMappingURL=chunk-
|
|
309
|
+
//# sourceMappingURL=chunk-WVJJN6XK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { z } from 'zod'\nimport { LICENSE_IDS, INTENTS, evaluateUse, buildAttribution, ccVersionFor, lexicalReranker } from '@refkit/core'\nimport type { RefkitClient, Reference, Verdict, Attribution, SearchFilters, SearchControls, SearchControlKey, ProviderOptionsById, SearchMeta, RightsRecord, Modality } from '@refkit/core'\n\nconst MODALITIES = ['image', 'video', 'audio', 'text'] as const\nconst ORIENTATIONS = ['landscape', 'portrait', 'square'] as const\n// Legacy media.kind control values — kept in the dynamic enum because they stay\n// meaningful as upstream filter translations for providers that support the\n// media.kind control without declaring kinds.\nconst BASE_MEDIA_KINDS = ['photo', 'illustration', 'vector', 'film', 'animation'] as const\nconst SEARCH_CONTROL_KEYS = [\n 'orientation',\n 'color',\n 'language',\n 'sort',\n 'safety',\n 'license.commercial',\n 'license.modification',\n 'license.allowUnknown',\n 'media.kind',\n 'media.size',\n 'media.minWidth',\n 'media.minHeight',\n 'media.duration',\n 'creator.id',\n 'creator.name',\n 'text.copyright',\n 'page',\n] as const satisfies readonly SearchControlKey[]\n\nconst filtersSchema = z.object({\n color: z.string().optional(),\n orientation: z.enum(ORIENTATIONS).optional(),\n language: z.string().optional(),\n})\nconst searchControlKeySchema = z.enum(SEARCH_CONTROL_KEYS)\n\nfunction buildSearchControlsSchema(kindValues: [string, ...string[]]) {\n return z.object({\n orientation: z.enum(ORIENTATIONS).optional(),\n color: z.string().optional(),\n language: z.string().optional(),\n sort: z.enum(['relevance', 'latest', 'popular', 'interesting']).optional(),\n safety: z.enum(['strict', 'moderate', 'off']).optional(),\n license: z.object({\n commercial: z.boolean().optional(),\n modification: z.boolean().optional(),\n allowUnknown: z.boolean().optional(),\n }).optional(),\n media: z.object({\n kind: z.enum(kindValues).optional(),\n size: z.enum(['small', 'medium', 'large']).optional(),\n minWidth: z.number().int().nonnegative().optional(),\n minHeight: z.number().int().nonnegative().optional(),\n duration: z.enum(['short', 'medium', 'long']).optional(),\n }).optional(),\n creator: z.object({\n id: z.string().optional(),\n name: z.string().optional(),\n }).optional(),\n text: z.object({\n copyright: z.enum(['public-domain', 'copyrighted', 'any']).optional(),\n }).optional(),\n page: z.number().int().positive().optional(),\n })\n}\n\nconst providerOptionValueSchema = z.union([z.string(), z.number(), z.boolean(), z.array(z.string())])\nconst providerOptionsSchema = z.record(z.string(), z.record(z.string(), providerOptionValueSchema))\n\n// Reported in the MCP initialize handshake. Read the real version (the dist sits\n// next to package.json, which npm always ships) instead of a hardcoded placeholder.\nconst VERSION: string = (() => {\n try {\n return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version\n } catch {\n return '0.0.0'\n }\n})()\n\n// Concise, agent-facing projection of a Reference (no raw provider dump). When an\n// intent is supplied the use-gate verdict + attribution ride along, so the agent\n// sees *whether it may use* each result — not just a bare license id it ignores.\nfunction toAgentRef(r: Reference, assessment?: { verdict: Verdict; attribution: Attribution }) {\n const base = {\n id: r.id,\n title: r.title,\n modality: r.modality,\n kind: r.kind,\n provider: r.source.providerId,\n canonicalUrl: r.canonicalUrl,\n license: r.rights.license,\n thumbnail: r.thumbnail?.url,\n excerpt: r.text?.excerpt,\n }\n if (!assessment) return base\n const { verdict, attribution } = assessment\n const reason = verdict.reasons.join('; ')\n const useExplanation = `${verdict.decision}: ${reason || 'license facts allow this use'}${attribution.required && attribution.text ? ` Attribution required: ${attribution.text}` : ''}`\n return {\n ...base,\n useVerdict: { decision: verdict.decision, reason: verdict.reasons.join('; '), confidence: verdict.confidence },\n useExplanation,\n ...(attribution.required && attribution.text ? { attribution: attribution.text } : {}),\n }\n}\n\nconst agentRefSchema = z.object({\n id: z.string(),\n title: z.string().optional(),\n modality: z.string(),\n kind: z.string().optional().describe('fine-grained resource kind, e.g. photo / texture / ebook'),\n provider: z.string(),\n canonicalUrl: z.string(),\n license: z.string(),\n thumbnail: z.string().optional(),\n excerpt: z.string().optional(),\n useVerdict: z\n .object({ decision: z.string(), reason: z.string(), confidence: z.string() })\n .optional()\n .describe('present when `intent` (or `gateFor`) is set: may this be used for that intent, and how confident'),\n useExplanation: z.string().optional().describe('plain-language use verdict summary for agents'),\n attribution: z.string().optional().describe('ready-to-use credit line; present when the license requires attribution'),\n})\n\nconst searchMetaSchema: z.ZodType<SearchMeta> = z.object({\n query: z.string(),\n modalities: z.array(z.enum(MODALITIES)),\n limit: z.number(),\n poolFactor: z.number(),\n fetchLimit: z.number(),\n appliedFilters: filtersSchema.optional(),\n controls: z.object({\n requested: z.array(searchControlKeySchema),\n appliedByProvider: z.record(z.string(), z.array(searchControlKeySchema)),\n ignoredByProvider: z.record(z.string(), z.array(searchControlKeySchema)),\n }).optional(),\n providerOptions: z.array(z.string()).optional(),\n providers: z.array(z.object({\n providerId: z.string(),\n status: z.enum(['fulfilled', 'failed', 'skipped']),\n returned: z.number().optional(),\n accepted: z.number().optional(),\n rejected: z.number().optional(),\n reason: z.enum(['unsupported-modality', 'unsupported-kind', 'not-selected']).optional(),\n error: z.string().optional(),\n latencyMs: z.number().optional(),\n cached: z.boolean().optional(),\n })),\n gate: z.object({\n intent: z.enum(INTENTS),\n before: z.number(),\n after: z.number(),\n dropped: z.number(),\n }).optional(),\n nextCursor: z.string().optional().describe('opaque load-more cursor; pass back as `cursor` to fetch the next page with cross-page dedup'),\n warnings: z.array(z.string()),\n})\n\n/** Wrap a configured RefkitClient as an MCP server exposing `search_references`. */\nexport function createRefkitMcpServer(refkit: RefkitClient): McpServer {\n const server = new McpServer({ name: 'refkit', version: VERSION })\n // Enumerated in the `sources` param description so an agent knows the valid ids\n // up front (and reused to enrich a source-miss error). Providers are fixed for\n // the server's lifetime, so this snapshot never drifts.\n const enabledSourceIds = refkit.providers.map(p => p.id)\n\n const registered = refkit.providers\n const modalityValues = [...new Set(registered.flatMap(p => p.modalities))] as [Modality, ...Modality[]]\n const kindValues = [...new Set<string>([...BASE_MEDIA_KINDS, ...registered.flatMap(p => p.kinds ?? [])])] as [string, ...string[]]\n const sourceList = registered.map(p => {\n const kinds = p.kinds?.length ? `·${p.kinds.join(',')}` : ''\n const desc = p.description ? `: ${p.description}` : ''\n return `- ${p.id} (${p.modalities.join('/')}${kinds})${desc}`\n }).join('\\n')\n const searchControlsSchema = buildSearchControlsSchema(kindValues)\n\n server.registerTool(\n 'search_references',\n {\n title: 'Search creative references',\n description:\n 'Search license-normalized reference material (image / video / audio / text) across the configured sources. ' +\n 'Every result carries a license id + canonical source link. Pass `intent` to annotate each result with a ' +\n 'use-verdict (may I use this, is attribution required) WITHOUT filtering; pass `gateFor` to instead return ' +\n 'only results whose license allows that intent. Results are references, not rights clearance — not legal advice.' +\n '\\n\\nConfigured sources:\\n' + sourceList,\n inputSchema: {\n query: z.string().describe('what to search for, e.g. \"cyberpunk alley at night\"'),\n modalities: z.array(z.enum(modalityValues)).optional().describe('default [\"image\"]'),\n sources: z.array(z.string()).optional().describe(\n 'restrict the search to specific sources by id (omit to search every configured source — see \"Configured sources\" in this tool description). '\n + 'Use to scope a search-engine operator (e.g. \"site:example.com\") to a web-discovery source without affecting other sources\\' queries.',\n ),\n filters: filtersSchema.optional().describe('compatibility alias for controls.orientation, controls.color, and controls.language'),\n controls: searchControlsSchema.optional().describe('provider-neutral search controls; providers translate supported controls and report ignored controls in explain metadata'),\n providerOptions: providerOptionsSchema.optional().describe('provider-specific search controls keyed by provider id; each provider whitelists supported keys'),\n explain: z.boolean().optional().describe('include provider status, applied and ignored controls, warnings, gate/drop metadata, and the load-more cursor'),\n limit: z.number().int().positive().optional(),\n cursor: z.string().optional().describe('opaque cursor from a previous result\\'s nextCursor — fetches the next batch, deduped against earlier batches'),\n rerank: z.boolean().optional().describe('re-rank results by query relevance (term coverage incl. CJK, resolution, source diversity) instead of raw cross-source rank fusion'),\n intent: z.enum(INTENTS).optional().describe('annotate each result with a use-verdict for this intended use (no filtering)'),\n gateFor: z.enum(INTENTS).optional().describe('only return results whose license allows this intended use'),\n },\n outputSchema: {\n references: z.array(agentRefSchema),\n nextCursor: z.string().optional().describe('pass back as `cursor` for the next batch; absent = exhausted'),\n meta: searchMetaSchema.optional(),\n },\n },\n async ({ query, modalities, filters, controls, providerOptions, explain, limit, cursor, rerank, intent, gateFor, sources }) => {\n const searchInput = {\n query,\n modalities: modalities ?? ['image'],\n sources,\n filters: filters as SearchFilters | undefined,\n controls: controls as SearchControls | undefined,\n providerOptions: providerOptions as ProviderOptionsById | undefined,\n limit,\n cursor,\n ...(rerank ? { rerank: lexicalReranker() } : {}),\n gateFor,\n }\n // Always searchWithMeta: the continuation token (meta.nextCursor) must not\n // depend on the explain diagnostics flag — only the meta DUMP is gated.\n let result\n try {\n result = await refkit.searchWithMeta(searchInput)\n } catch (err) {\n // A source-selection miss (no requested id resolves for the modality) is a\n // caller mistake, not an outage — turn core's throw into an agent-actionable\n // tool error listing the valid ids. AggregateError (every chosen provider\n // failed at fetch) is a genuine upstream fault, so let it propagate.\n if (sources && sources.length > 0 && !(err instanceof AggregateError)) {\n const available = enabledSourceIds.join(', ') || '(none)'\n const detail = err instanceof Error ? err.message : String(err)\n return {\n isError: true,\n content: [{ type: 'text', text: `${detail} Enabled source ids: ${available}.` }],\n }\n }\n throw err\n }\n const refs = result.references\n const assessIntent = intent ?? gateFor\n const references = refs.map(r =>\n assessIntent\n ? toAgentRef(r, { verdict: refkit.evaluateUse(r, assessIntent), attribution: refkit.buildAttribution(r) })\n : toAgentRef(r),\n )\n return {\n content: [{ type: 'text', text: `${references.length} reference(s) for \"${query}\".` }],\n structuredContent: {\n references,\n ...(result.meta.nextCursor ? { nextCursor: result.meta.nextCursor } : {}),\n ...(explain ? { meta: result.meta } : {}),\n },\n }\n },\n )\n\n const attributionOutputSchema = { required: z.boolean(), text: z.string().optional(), html: z.string().optional() }\n\n server.registerTool(\n 'evaluate_use',\n {\n title: 'Evaluate a license for an intended use',\n description:\n 'Stateless license/use-gate check: given a license id + intended use, returns a conservative-heuristic verdict ' +\n '(allowed / allowed-with-attribution / denied / needs-review) with reasons and confidence. ' +\n 'Not legal advice — a strict-deny heuristic over source-declared license facts.',\n inputSchema: {\n license: z.enum(LICENSE_IDS).describe('the reference\\'s license id'),\n licenseVersion: z.string().optional().describe('precise CC version, e.g. \"4.0\" — attribution only'),\n author: z.string().optional(),\n title: z.string().optional(),\n canonicalUrl: z.string().describe('canonical source link, for attribution and audit'),\n intent: z.enum(INTENTS).describe('the intended use to evaluate this license against'),\n editorialOnly: z.boolean().optional().describe('source marked editorial-only'),\n jurisdiction: z.string().optional().describe('source-declared jurisdiction of the PD/copyright status'),\n userJurisdiction: z.string().optional().describe('caller\\'s jurisdiction; mismatched jurisdictions default to needs-review'),\n },\n outputSchema: {\n decision: z.enum(['allowed', 'allowed-with-attribution', 'denied', 'needs-review']),\n reasons: z.array(z.string()),\n confidence: z.enum(['high', 'low']),\n disclaimer: z.string(),\n attribution: z.object(attributionOutputSchema).optional(),\n },\n },\n async ({ license, licenseVersion, author, title, canonicalUrl, intent, editorialOnly, jurisdiction, userJurisdiction }) => {\n const version = ccVersionFor(license, licenseVersion)\n const rights: RightsRecord = {\n license,\n licenseVersion: version,\n author,\n rehostPolicy: 'cache-allowed',\n jurisdiction,\n editorialOnly,\n raw: { sourceTerms: '', sourceUrl: canonicalUrl },\n }\n const verdict: Verdict = evaluateUse(rights, intent, { userJurisdiction })\n const attribution =\n verdict.decision === 'allowed-with-attribution'\n ? buildAttribution({ license, licenseVersion: version, author, title, canonicalUrl })\n : undefined\n const summary = `${verdict.decision}: ${verdict.reasons.join('; ') || 'license facts allow this use'}`\n return {\n content: [{ type: 'text', text: summary }],\n structuredContent: {\n decision: verdict.decision,\n reasons: verdict.reasons,\n confidence: verdict.confidence,\n disclaimer: verdict.disclaimer,\n ...(attribution ? { attribution } : {}),\n },\n }\n },\n )\n\n server.registerTool(\n 'build_attribution',\n {\n title: 'Build an attribution credit line',\n description:\n 'Mechanically derive an attribution credit line (plain text + HTML) from a license id + author + title + ' +\n 'canonicalUrl. `required` is false when the license needs no attribution (e.g. CC0, PD).',\n inputSchema: {\n license: z.enum(LICENSE_IDS),\n licenseVersion: z.string().optional().describe('precise CC version, e.g. \"4.0\" — appended to the license name'),\n author: z.string().optional(),\n title: z.string().optional(),\n canonicalUrl: z.string(),\n },\n outputSchema: attributionOutputSchema,\n },\n async ({ license, licenseVersion, author, title, canonicalUrl }) => {\n const version = ccVersionFor(license, licenseVersion)\n const attribution: Attribution = buildAttribution({ license, licenseVersion: version, author, title, canonicalUrl })\n return {\n content: [{ type: 'text', text: attribution.required ? (attribution.text ?? '') : 'No attribution required for this license.' }],\n structuredContent: { required: attribution.required, text: attribution.text, html: attribution.html },\n }\n },\n )\n\n return server\n}\n\n/** Run the refkit MCP server over stdio (host wires the RefkitClient + its providers/keys). */\nexport async function serveStdio(refkit: RefkitClient): Promise<void> {\n const server = createRefkitMcpServer(refkit)\n await server.connect(new StdioServerTransport())\n}\n"],"mappings":"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","names":[]}
|
package/dist/cli.d.ts
CHANGED
|
@@ -16,5 +16,10 @@ declare const BYOK_SOURCES: ByokSource[];
|
|
|
16
16
|
* (optionalDependencies, dynamically imported on demand). Exported so the
|
|
17
17
|
* wiring is unit-testable. */
|
|
18
18
|
declare function defaultProviders(env?: NodeJS.ProcessEnv): Promise<ReferenceProvider[]>;
|
|
19
|
+
/** Cursor size knob for size-clamped tool-output channels: REFKIT_MAX_CURSOR_SEEN
|
|
20
|
+
* caps how many already-returned keys the load-more cursor remembers (see
|
|
21
|
+
* RefkitOptions.maxCursorSeen in @refkit/core — default 500 ≈ 2.7k chars of
|
|
22
|
+
* nextCursor). Invalid values warn on stderr and fall back to that default. */
|
|
23
|
+
declare function maxCursorSeenFromEnv(env?: NodeJS.ProcessEnv): number | undefined;
|
|
19
24
|
|
|
20
|
-
export { BYOK_SOURCES, defaultProviders };
|
|
25
|
+
export { BYOK_SOURCES, defaultProviders, maxCursorSeenFromEnv };
|
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
serveStdio
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-WVJJN6XK.js";
|
|
5
5
|
|
|
6
6
|
// src/cli.ts
|
|
7
7
|
import { realpathSync } from "fs";
|
|
@@ -16,6 +16,7 @@ import { poetrydb } from "@refkit/provider-poetrydb";
|
|
|
16
16
|
import { rijksmuseum } from "@refkit/provider-rijksmuseum";
|
|
17
17
|
import { polyhaven, ambientcg } from "@refkit/provider-polyhaven";
|
|
18
18
|
import { internetArchive } from "@refkit/provider-internet-archive";
|
|
19
|
+
import { nailbook } from "@refkit/provider-nailbook";
|
|
19
20
|
var BYOK_SOURCES = [
|
|
20
21
|
{
|
|
21
22
|
pkg: "@refkit/provider-unsplash",
|
|
@@ -81,7 +82,8 @@ async function defaultProviders(env = process.env) {
|
|
|
81
82
|
rijksmuseum(),
|
|
82
83
|
polyhaven(),
|
|
83
84
|
ambientcg(),
|
|
84
|
-
internetArchive()
|
|
85
|
+
internetArchive(),
|
|
86
|
+
nailbook()
|
|
85
87
|
];
|
|
86
88
|
const loaded = await Promise.all(BYOK_SOURCES.map(async (source) => {
|
|
87
89
|
const key = source.key(env);
|
|
@@ -109,11 +111,26 @@ var isEntry = (() => {
|
|
|
109
111
|
return false;
|
|
110
112
|
}
|
|
111
113
|
})();
|
|
114
|
+
function maxCursorSeenFromEnv(env = process.env) {
|
|
115
|
+
const raw = env.REFKIT_MAX_CURSOR_SEEN;
|
|
116
|
+
if (raw === void 0 || raw === "") return void 0;
|
|
117
|
+
const n = /^\d+$/.test(raw) ? Number(raw) : Number.NaN;
|
|
118
|
+
if (!Number.isSafeInteger(n) || n < 1) {
|
|
119
|
+
console.error(`[refkit-mcp] ignoring invalid REFKIT_MAX_CURSOR_SEEN=${JSON.stringify(raw)} \u2014 expected a positive integer.`);
|
|
120
|
+
return void 0;
|
|
121
|
+
}
|
|
122
|
+
return n;
|
|
123
|
+
}
|
|
112
124
|
if (isEntry) {
|
|
113
|
-
|
|
125
|
+
const maxCursorSeen = maxCursorSeenFromEnv();
|
|
126
|
+
await serveStdio(createRefkit({
|
|
127
|
+
providers: await defaultProviders(),
|
|
128
|
+
...maxCursorSeen !== void 0 ? { maxCursorSeen } : {}
|
|
129
|
+
}));
|
|
114
130
|
}
|
|
115
131
|
export {
|
|
116
132
|
BYOK_SOURCES,
|
|
117
|
-
defaultProviders
|
|
133
|
+
defaultProviders,
|
|
134
|
+
maxCursorSeenFromEnv
|
|
118
135
|
};
|
|
119
136
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n// Zero-config entry: `npx @refkit/mcp` boots a working MCP server with the keyless\n// providers, plus any BYOK provider whose key is in the environment. No host code.\nimport { realpathSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { createRefkit, type ReferenceProvider } from '@refkit/core'\nimport { openverse, openverseAudio } from '@refkit/provider-openverse'\nimport { wikimediaCommons } from '@refkit/provider-wikimedia-commons'\nimport { met } from '@refkit/provider-met'\nimport { artic } from '@refkit/provider-artic'\nimport { gutendex } from '@refkit/provider-gutendex'\nimport { poetrydb } from '@refkit/provider-poetrydb'\nimport { rijksmuseum } from '@refkit/provider-rijksmuseum'\nimport { polyhaven, ambientcg } from '@refkit/provider-polyhaven'\nimport { internetArchive } from '@refkit/provider-internet-archive'\nimport { serveStdio } from './index'\n\n/** One BYOK source: its unified + legacy env var names, and a lazy loader for its\n * (optional) provider package. Loaded only when a key is present, so installs\n * that omitted optionalDependencies still boot — the missing source is skipped\n * with a stderr warning instead of crashing the server. */\ninterface ByokSource {\n pkg: string\n key: (env: NodeJS.ProcessEnv) => string | undefined\n load: (key: string) => Promise<ReferenceProvider[]>\n}\n\n// Env var convention: each BYOK key is read as `REFKIT_<PROVIDER>_KEY` first (the\n// unified name), falling back to the provider's legacy env var name — both are\n// honored indefinitely, the unified name is just preferred going forward.\n// Exported so tests can assert this table stays in sync with the package's\n// optionalDependencies — an entry in one but not the other ships a source that\n// either can never load or never installs.\nexport const BYOK_SOURCES: ByokSource[] = [\n {\n pkg: '@refkit/provider-unsplash',\n key: (env) => env.REFKIT_UNSPLASH_KEY ?? env.UNSPLASH_KEY,\n load: async (accessKey) => [(await import('@refkit/provider-unsplash')).unsplash({ accessKey })],\n },\n {\n pkg: '@refkit/provider-pexels',\n key: (env) => env.REFKIT_PEXELS_KEY ?? env.PEXELS_KEY,\n load: async (apiKey) => {\n const m = await import('@refkit/provider-pexels')\n return [m.pexels({ apiKey }), m.pexelsVideo({ apiKey })]\n },\n },\n {\n pkg: '@refkit/provider-pixabay',\n key: (env) => env.REFKIT_PIXABAY_KEY ?? env.PIXABAY_KEY,\n load: async (key) => {\n const m = await import('@refkit/provider-pixabay')\n return [m.pixabay({ key }), m.pixabayVideo({ key })]\n },\n },\n {\n pkg: '@refkit/provider-flickr',\n key: (env) => env.REFKIT_FLICKR_KEY ?? env.FLICKR_KEY,\n load: async (apiKey) => [(await import('@refkit/provider-flickr')).flickr({ apiKey })],\n },\n {\n pkg: '@refkit/provider-smithsonian',\n key: (env) => env.REFKIT_SMITHSONIAN_KEY ?? env.SI_KEY,\n load: async (apiKey) => [(await import('@refkit/provider-smithsonian')).smithsonian({ apiKey })],\n },\n {\n pkg: '@refkit/provider-brave',\n key: (env) => env.REFKIT_BRAVE_KEY ?? env.BRAVE_TOKEN,\n load: async (token) => [(await import('@refkit/provider-brave')).brave({ token })],\n },\n {\n pkg: '@refkit/provider-freesound',\n key: (env) => env.REFKIT_FREESOUND_KEY ?? env.FREESOUND_TOKEN,\n load: async (apiKey) => [(await import('@refkit/provider-freesound')).freesound({ apiKey })],\n },\n {\n pkg: '@refkit/provider-jamendo',\n key: (env) => env.REFKIT_JAMENDO_CLIENT_ID ?? env.JAMENDO_CLIENT_ID,\n load: async (clientId) => [(await import('@refkit/provider-jamendo')).jamendo({ clientId })],\n },\n {\n pkg: '@refkit/provider-europeana',\n key: (env) => env.REFKIT_EUROPEANA_KEY ?? env.EUROPEANA_KEY,\n load: async (apiKey) => [(await import('@refkit/provider-europeana')).europeana({ apiKey })],\n },\n]\n\n/** Providers a zero-config server boots with: all keyless sources (hard deps,\n * statically imported), plus any BYOK source whose key is present in `env`\n * (optionalDependencies, dynamically imported on demand). Exported so the\n * wiring is unit-testable. */\nexport async function defaultProviders(env: NodeJS.ProcessEnv = process.env): Promise<ReferenceProvider[]> {\n const providers: ReferenceProvider[] = [\n openverse(), openverseAudio(), wikimediaCommons(), met(), artic(), gutendex(), poetrydb(),\n rijksmuseum(), polyhaven(), ambientcg(), internetArchive(),\n ]\n // Independent module loads — run them concurrently (startup cost = max, not sum)\n // and keep BYOK_SOURCES order in the provider list.\n const loaded = await Promise.all(BYOK_SOURCES.map(async (source) => {\n const key = source.key(env)\n if (!key) return []\n try {\n return await source.load(key)\n } catch (err) {\n // stderr only — stdout is the MCP transport. Only a genuinely missing\n // module gets the \"not installed\" hint; anything else (factory throw,\n // broken transitive import) surfaces the REAL error so the operator\n // doesn't chase the wrong remediation.\n const code = (err as { code?: string } | null)?.code\n if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') {\n console.error(`[refkit-mcp] key for ${source.pkg} is set but the package is not installed — skipping this source. Reinstall @refkit/mcp with optional dependencies (or add ${source.pkg}) to enable it.`)\n } else {\n console.error(`[refkit-mcp] failed to initialize ${source.pkg} — skipping this source.`, err)\n }\n return []\n }\n }))\n for (const group of loaded) providers.push(...group)\n return providers\n}\n\n// Boot only when run as the CLI entry — not when imported (e.g. by tests). realpath\n// so an npm bin symlink resolves to this file.\nconst isEntry = (() => {\n if (!process.argv[1]) return false\n try {\n return realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)\n } catch {\n return false\n }\n})()\n\nif (isEntry) {\n await serveStdio(createRefkit({ providers: await defaultProviders() }))\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n// Zero-config entry: `npx @refkit/mcp` boots a working MCP server with the keyless\n// providers, plus any BYOK provider whose key is in the environment. No host code.\nimport { realpathSync } from 'node:fs'\nimport { fileURLToPath } from 'node:url'\nimport { createRefkit, type ReferenceProvider } from '@refkit/core'\nimport { openverse, openverseAudio } from '@refkit/provider-openverse'\nimport { wikimediaCommons } from '@refkit/provider-wikimedia-commons'\nimport { met } from '@refkit/provider-met'\nimport { artic } from '@refkit/provider-artic'\nimport { gutendex } from '@refkit/provider-gutendex'\nimport { poetrydb } from '@refkit/provider-poetrydb'\nimport { rijksmuseum } from '@refkit/provider-rijksmuseum'\nimport { polyhaven, ambientcg } from '@refkit/provider-polyhaven'\nimport { internetArchive } from '@refkit/provider-internet-archive'\nimport { nailbook } from '@refkit/provider-nailbook'\nimport { serveStdio } from './index'\n\n/** One BYOK source: its unified + legacy env var names, and a lazy loader for its\n * (optional) provider package. Loaded only when a key is present, so installs\n * that omitted optionalDependencies still boot — the missing source is skipped\n * with a stderr warning instead of crashing the server. */\ninterface ByokSource {\n pkg: string\n key: (env: NodeJS.ProcessEnv) => string | undefined\n load: (key: string) => Promise<ReferenceProvider[]>\n}\n\n// Env var convention: each BYOK key is read as `REFKIT_<PROVIDER>_KEY` first (the\n// unified name), falling back to the provider's legacy env var name — both are\n// honored indefinitely, the unified name is just preferred going forward.\n// Exported so tests can assert this table stays in sync with the package's\n// optionalDependencies — an entry in one but not the other ships a source that\n// either can never load or never installs.\nexport const BYOK_SOURCES: ByokSource[] = [\n {\n pkg: '@refkit/provider-unsplash',\n key: (env) => env.REFKIT_UNSPLASH_KEY ?? env.UNSPLASH_KEY,\n load: async (accessKey) => [(await import('@refkit/provider-unsplash')).unsplash({ accessKey })],\n },\n {\n pkg: '@refkit/provider-pexels',\n key: (env) => env.REFKIT_PEXELS_KEY ?? env.PEXELS_KEY,\n load: async (apiKey) => {\n const m = await import('@refkit/provider-pexels')\n return [m.pexels({ apiKey }), m.pexelsVideo({ apiKey })]\n },\n },\n {\n pkg: '@refkit/provider-pixabay',\n key: (env) => env.REFKIT_PIXABAY_KEY ?? env.PIXABAY_KEY,\n load: async (key) => {\n const m = await import('@refkit/provider-pixabay')\n return [m.pixabay({ key }), m.pixabayVideo({ key })]\n },\n },\n {\n pkg: '@refkit/provider-flickr',\n key: (env) => env.REFKIT_FLICKR_KEY ?? env.FLICKR_KEY,\n load: async (apiKey) => [(await import('@refkit/provider-flickr')).flickr({ apiKey })],\n },\n {\n pkg: '@refkit/provider-smithsonian',\n key: (env) => env.REFKIT_SMITHSONIAN_KEY ?? env.SI_KEY,\n load: async (apiKey) => [(await import('@refkit/provider-smithsonian')).smithsonian({ apiKey })],\n },\n {\n pkg: '@refkit/provider-brave',\n key: (env) => env.REFKIT_BRAVE_KEY ?? env.BRAVE_TOKEN,\n load: async (token) => [(await import('@refkit/provider-brave')).brave({ token })],\n },\n {\n pkg: '@refkit/provider-freesound',\n key: (env) => env.REFKIT_FREESOUND_KEY ?? env.FREESOUND_TOKEN,\n load: async (apiKey) => [(await import('@refkit/provider-freesound')).freesound({ apiKey })],\n },\n {\n pkg: '@refkit/provider-jamendo',\n key: (env) => env.REFKIT_JAMENDO_CLIENT_ID ?? env.JAMENDO_CLIENT_ID,\n load: async (clientId) => [(await import('@refkit/provider-jamendo')).jamendo({ clientId })],\n },\n {\n pkg: '@refkit/provider-europeana',\n key: (env) => env.REFKIT_EUROPEANA_KEY ?? env.EUROPEANA_KEY,\n load: async (apiKey) => [(await import('@refkit/provider-europeana')).europeana({ apiKey })],\n },\n]\n\n/** Providers a zero-config server boots with: all keyless sources (hard deps,\n * statically imported), plus any BYOK source whose key is present in `env`\n * (optionalDependencies, dynamically imported on demand). Exported so the\n * wiring is unit-testable. */\nexport async function defaultProviders(env: NodeJS.ProcessEnv = process.env): Promise<ReferenceProvider[]> {\n const providers: ReferenceProvider[] = [\n openverse(), openverseAudio(), wikimediaCommons(), met(), artic(), gutendex(), poetrydb(),\n rijksmuseum(), polyhaven(), ambientcg(), internetArchive(), nailbook(),\n ]\n // Independent module loads — run them concurrently (startup cost = max, not sum)\n // and keep BYOK_SOURCES order in the provider list.\n const loaded = await Promise.all(BYOK_SOURCES.map(async (source) => {\n const key = source.key(env)\n if (!key) return []\n try {\n return await source.load(key)\n } catch (err) {\n // stderr only — stdout is the MCP transport. Only a genuinely missing\n // module gets the \"not installed\" hint; anything else (factory throw,\n // broken transitive import) surfaces the REAL error so the operator\n // doesn't chase the wrong remediation.\n const code = (err as { code?: string } | null)?.code\n if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') {\n console.error(`[refkit-mcp] key for ${source.pkg} is set but the package is not installed — skipping this source. Reinstall @refkit/mcp with optional dependencies (or add ${source.pkg}) to enable it.`)\n } else {\n console.error(`[refkit-mcp] failed to initialize ${source.pkg} — skipping this source.`, err)\n }\n return []\n }\n }))\n for (const group of loaded) providers.push(...group)\n return providers\n}\n\n// Boot only when run as the CLI entry — not when imported (e.g. by tests). realpath\n// so an npm bin symlink resolves to this file.\nconst isEntry = (() => {\n if (!process.argv[1]) return false\n try {\n return realpathSync(process.argv[1]) === fileURLToPath(import.meta.url)\n } catch {\n return false\n }\n})()\n\n/** Cursor size knob for size-clamped tool-output channels: REFKIT_MAX_CURSOR_SEEN\n * caps how many already-returned keys the load-more cursor remembers (see\n * RefkitOptions.maxCursorSeen in @refkit/core — default 500 ≈ 2.7k chars of\n * nextCursor). Invalid values warn on stderr and fall back to that default. */\nexport function maxCursorSeenFromEnv(env: NodeJS.ProcessEnv = process.env): number | undefined {\n const raw = env.REFKIT_MAX_CURSOR_SEEN\n if (raw === undefined || raw === '') return undefined\n // Strict decimal digits only — Number()'s hex/exponent/whitespace leniency\n // would silently accept values like '1e100' that defeat the cap entirely.\n const n = /^\\d+$/.test(raw) ? Number(raw) : Number.NaN\n if (!Number.isSafeInteger(n) || n < 1) {\n console.error(`[refkit-mcp] ignoring invalid REFKIT_MAX_CURSOR_SEEN=${JSON.stringify(raw)} — expected a positive integer.`)\n return undefined\n }\n return n\n}\n\nif (isEntry) {\n const maxCursorSeen = maxCursorSeenFromEnv()\n await serveStdio(createRefkit({\n providers: await defaultProviders(),\n ...(maxCursorSeen !== undefined ? { maxCursorSeen } : {}),\n }))\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refkit/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "MCP server for refkit — exposes license-normalized reference search as an agent tool.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -34,31 +34,32 @@
|
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
36
36
|
"zod": "^4.3.6",
|
|
37
|
-
"@refkit/core": "0.
|
|
38
|
-
"@refkit/provider-artic": "0.
|
|
39
|
-
"@refkit/provider-gutendex": "0.
|
|
40
|
-
"@refkit/provider-internet-archive": "0.
|
|
41
|
-
"@refkit/provider-met": "0.
|
|
42
|
-
"@refkit/provider-
|
|
43
|
-
"@refkit/provider-
|
|
44
|
-
"@refkit/provider-
|
|
45
|
-
"@refkit/provider-
|
|
46
|
-
"@refkit/provider-
|
|
37
|
+
"@refkit/core": "0.8.0",
|
|
38
|
+
"@refkit/provider-artic": "0.3.0",
|
|
39
|
+
"@refkit/provider-gutendex": "0.3.0",
|
|
40
|
+
"@refkit/provider-internet-archive": "0.4.0",
|
|
41
|
+
"@refkit/provider-met": "0.3.0",
|
|
42
|
+
"@refkit/provider-nailbook": "0.1.0",
|
|
43
|
+
"@refkit/provider-openverse": "0.4.0",
|
|
44
|
+
"@refkit/provider-poetrydb": "0.3.0",
|
|
45
|
+
"@refkit/provider-polyhaven": "0.3.0",
|
|
46
|
+
"@refkit/provider-rijksmuseum": "0.3.0",
|
|
47
|
+
"@refkit/provider-wikimedia-commons": "0.4.0"
|
|
47
48
|
},
|
|
48
49
|
"files": [
|
|
49
50
|
"dist",
|
|
50
51
|
"LICENSE"
|
|
51
52
|
],
|
|
52
53
|
"optionalDependencies": {
|
|
53
|
-
"@refkit/provider-
|
|
54
|
-
"@refkit/provider-
|
|
55
|
-
"@refkit/provider-
|
|
56
|
-
"@refkit/provider-
|
|
57
|
-
"@refkit/provider-jamendo": "0.
|
|
58
|
-
"@refkit/provider-
|
|
59
|
-
"@refkit/provider-
|
|
60
|
-
"@refkit/provider-
|
|
61
|
-
"@refkit/provider-unsplash": "0.
|
|
54
|
+
"@refkit/provider-flickr": "0.4.0",
|
|
55
|
+
"@refkit/provider-brave": "0.3.0",
|
|
56
|
+
"@refkit/provider-freesound": "0.4.0",
|
|
57
|
+
"@refkit/provider-europeana": "0.4.0",
|
|
58
|
+
"@refkit/provider-jamendo": "0.4.0",
|
|
59
|
+
"@refkit/provider-pixabay": "0.3.0",
|
|
60
|
+
"@refkit/provider-smithsonian": "0.3.0",
|
|
61
|
+
"@refkit/provider-pexels": "0.3.0",
|
|
62
|
+
"@refkit/provider-unsplash": "0.3.0"
|
|
62
63
|
},
|
|
63
64
|
"scripts": {
|
|
64
65
|
"typecheck": "tsc --noEmit",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'\nimport { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'\nimport { z } from 'zod'\nimport { LICENSE_IDS, INTENTS, evaluateUse, buildAttribution, ccVersionFor, lexicalReranker } from '@refkit/core'\nimport type { RefkitClient, Reference, Verdict, Attribution, SearchFilters, SearchControls, SearchControlKey, ProviderOptionsById, SearchMeta, RightsRecord } from '@refkit/core'\n\nconst MODALITIES = ['image', 'video', 'audio', 'text'] as const\nconst ORIENTATIONS = ['landscape', 'portrait', 'square'] as const\nconst SEARCH_CONTROL_KEYS = [\n 'orientation',\n 'color',\n 'language',\n 'sort',\n 'safety',\n 'license.commercial',\n 'license.modification',\n 'license.allowUnknown',\n 'media.kind',\n 'media.size',\n 'media.minWidth',\n 'media.minHeight',\n 'media.duration',\n 'creator.id',\n 'creator.name',\n 'text.copyright',\n 'page',\n] as const satisfies readonly SearchControlKey[]\n\nconst filtersSchema = z.object({\n color: z.string().optional(),\n orientation: z.enum(ORIENTATIONS).optional(),\n language: z.string().optional(),\n})\nconst searchControlKeySchema = z.enum(SEARCH_CONTROL_KEYS)\n\nconst searchControlsSchema = z.object({\n orientation: z.enum(ORIENTATIONS).optional(),\n color: z.string().optional(),\n language: z.string().optional(),\n sort: z.enum(['relevance', 'latest', 'popular', 'interesting']).optional(),\n safety: z.enum(['strict', 'moderate', 'off']).optional(),\n license: z.object({\n commercial: z.boolean().optional(),\n modification: z.boolean().optional(),\n allowUnknown: z.boolean().optional(),\n }).optional(),\n media: z.object({\n kind: z.enum(['photo', 'illustration', 'vector', 'film', 'animation']).optional(),\n size: z.enum(['small', 'medium', 'large']).optional(),\n minWidth: z.number().int().nonnegative().optional(),\n minHeight: z.number().int().nonnegative().optional(),\n duration: z.enum(['short', 'medium', 'long']).optional(),\n }).optional(),\n creator: z.object({\n id: z.string().optional(),\n name: z.string().optional(),\n }).optional(),\n text: z.object({\n copyright: z.enum(['public-domain', 'copyrighted', 'any']).optional(),\n }).optional(),\n page: z.number().int().positive().optional(),\n})\n\nconst providerOptionValueSchema = z.union([z.string(), z.number(), z.boolean(), z.array(z.string())])\nconst providerOptionsSchema = z.record(z.string(), z.record(z.string(), providerOptionValueSchema))\n\n// Reported in the MCP initialize handshake. Read the real version (the dist sits\n// next to package.json, which npm always ships) instead of a hardcoded placeholder.\nconst VERSION: string = (() => {\n try {\n return JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8')).version\n } catch {\n return '0.0.0'\n }\n})()\n\n// Concise, agent-facing projection of a Reference (no raw provider dump). When an\n// intent is supplied the use-gate verdict + attribution ride along, so the agent\n// sees *whether it may use* each result — not just a bare license id it ignores.\nfunction toAgentRef(r: Reference, assessment?: { verdict: Verdict; attribution: Attribution }) {\n const base = {\n id: r.id,\n title: r.title,\n modality: r.modality,\n provider: r.source.providerId,\n canonicalUrl: r.canonicalUrl,\n license: r.rights.license,\n thumbnail: r.thumbnail?.url,\n excerpt: r.text?.excerpt,\n }\n if (!assessment) return base\n const { verdict, attribution } = assessment\n const reason = verdict.reasons.join('; ')\n const useExplanation = `${verdict.decision}: ${reason || 'license facts allow this use'}${attribution.required && attribution.text ? ` Attribution required: ${attribution.text}` : ''}`\n return {\n ...base,\n useVerdict: { decision: verdict.decision, reason: verdict.reasons.join('; '), confidence: verdict.confidence },\n useExplanation,\n ...(attribution.required && attribution.text ? { attribution: attribution.text } : {}),\n }\n}\n\nconst agentRefSchema = z.object({\n id: z.string(),\n title: z.string().optional(),\n modality: z.string(),\n provider: z.string(),\n canonicalUrl: z.string(),\n license: z.string(),\n thumbnail: z.string().optional(),\n excerpt: z.string().optional(),\n useVerdict: z\n .object({ decision: z.string(), reason: z.string(), confidence: z.string() })\n .optional()\n .describe('present when `intent` (or `gateFor`) is set: may this be used for that intent, and how confident'),\n useExplanation: z.string().optional().describe('plain-language use verdict summary for agents'),\n attribution: z.string().optional().describe('ready-to-use credit line; present when the license requires attribution'),\n})\n\nconst searchMetaSchema: z.ZodType<SearchMeta> = z.object({\n query: z.string(),\n modalities: z.array(z.enum(MODALITIES)),\n limit: z.number(),\n poolFactor: z.number(),\n fetchLimit: z.number(),\n appliedFilters: filtersSchema.optional(),\n controls: z.object({\n requested: z.array(searchControlKeySchema),\n appliedByProvider: z.record(z.string(), z.array(searchControlKeySchema)),\n ignoredByProvider: z.record(z.string(), z.array(searchControlKeySchema)),\n }).optional(),\n providerOptions: z.array(z.string()).optional(),\n providers: z.array(z.object({\n providerId: z.string(),\n status: z.enum(['fulfilled', 'failed', 'skipped']),\n returned: z.number().optional(),\n accepted: z.number().optional(),\n rejected: z.number().optional(),\n reason: z.enum(['unsupported-modality']).optional(),\n error: z.string().optional(),\n latencyMs: z.number().optional(),\n cached: z.boolean().optional(),\n })),\n gate: z.object({\n intent: z.enum(INTENTS),\n before: z.number(),\n after: z.number(),\n dropped: z.number(),\n }).optional(),\n nextCursor: z.string().optional().describe('opaque load-more cursor; pass back as `cursor` to fetch the next page with cross-page dedup'),\n warnings: z.array(z.string()),\n})\n\n/** Wrap a configured RefkitClient as an MCP server exposing `search_references`. */\nexport function createRefkitMcpServer(refkit: RefkitClient): McpServer {\n const server = new McpServer({ name: 'refkit', version: VERSION })\n\n server.registerTool(\n 'search_references',\n {\n title: 'Search creative references',\n description:\n 'Search license-normalized reference material (image / video / audio / text) across the configured sources. ' +\n 'Every result carries a license id + canonical source link. Pass `intent` to annotate each result with a ' +\n 'use-verdict (may I use this, is attribution required) WITHOUT filtering; pass `gateFor` to instead return ' +\n 'only results whose license allows that intent. Results are references, not rights clearance — not legal advice.',\n inputSchema: {\n query: z.string().describe('what to search for, e.g. \"cyberpunk alley at night\"'),\n modalities: z.array(z.enum(MODALITIES)).optional().describe('default [\"image\"]'),\n filters: filtersSchema.optional().describe('compatibility alias for controls.orientation, controls.color, and controls.language'),\n controls: searchControlsSchema.optional().describe('provider-neutral search controls; providers translate supported controls and report ignored controls in explain metadata'),\n providerOptions: providerOptionsSchema.optional().describe('provider-specific search controls keyed by provider id; each provider whitelists supported keys'),\n explain: z.boolean().optional().describe('include provider status, applied and ignored controls, warnings, gate/drop metadata, and the load-more cursor'),\n limit: z.number().int().positive().optional(),\n cursor: z.string().optional().describe('opaque cursor from a previous result\\'s nextCursor — fetches the next batch, deduped against earlier batches'),\n rerank: z.boolean().optional().describe('re-rank results by query relevance (term coverage incl. CJK, resolution, source diversity) instead of raw cross-source rank fusion'),\n intent: z.enum(INTENTS).optional().describe('annotate each result with a use-verdict for this intended use (no filtering)'),\n gateFor: z.enum(INTENTS).optional().describe('only return results whose license allows this intended use'),\n },\n outputSchema: {\n references: z.array(agentRefSchema),\n nextCursor: z.string().optional().describe('pass back as `cursor` for the next batch; absent = exhausted'),\n meta: searchMetaSchema.optional(),\n },\n },\n async ({ query, modalities, filters, controls, providerOptions, explain, limit, cursor, rerank, intent, gateFor }) => {\n const searchInput = {\n query,\n modalities: modalities ?? ['image'],\n filters: filters as SearchFilters | undefined,\n controls: controls as SearchControls | undefined,\n providerOptions: providerOptions as ProviderOptionsById | undefined,\n limit,\n cursor,\n ...(rerank ? { rerank: lexicalReranker() } : {}),\n gateFor,\n }\n // Always searchWithMeta: the continuation token (meta.nextCursor) must not\n // depend on the explain diagnostics flag — only the meta DUMP is gated.\n const result = await refkit.searchWithMeta(searchInput)\n const refs = result.references\n const assessIntent = intent ?? gateFor\n const references = refs.map(r =>\n assessIntent\n ? toAgentRef(r, { verdict: refkit.evaluateUse(r, assessIntent), attribution: refkit.buildAttribution(r) })\n : toAgentRef(r),\n )\n return {\n content: [{ type: 'text', text: `${references.length} reference(s) for \"${query}\".` }],\n structuredContent: {\n references,\n ...(result.meta.nextCursor ? { nextCursor: result.meta.nextCursor } : {}),\n ...(explain ? { meta: result.meta } : {}),\n },\n }\n },\n )\n\n const attributionOutputSchema = { required: z.boolean(), text: z.string().optional(), html: z.string().optional() }\n\n server.registerTool(\n 'evaluate_use',\n {\n title: 'Evaluate a license for an intended use',\n description:\n 'Stateless license/use-gate check: given a license id + intended use, returns a conservative-heuristic verdict ' +\n '(allowed / allowed-with-attribution / denied / needs-review) with reasons and confidence. ' +\n 'Not legal advice — a strict-deny heuristic over source-declared license facts.',\n inputSchema: {\n license: z.enum(LICENSE_IDS).describe('the reference\\'s license id'),\n licenseVersion: z.string().optional().describe('precise CC version, e.g. \"4.0\" — attribution only'),\n author: z.string().optional(),\n title: z.string().optional(),\n canonicalUrl: z.string().describe('canonical source link, for attribution and audit'),\n intent: z.enum(INTENTS).describe('the intended use to evaluate this license against'),\n editorialOnly: z.boolean().optional().describe('source marked editorial-only'),\n jurisdiction: z.string().optional().describe('source-declared jurisdiction of the PD/copyright status'),\n userJurisdiction: z.string().optional().describe('caller\\'s jurisdiction; mismatched jurisdictions default to needs-review'),\n },\n outputSchema: {\n decision: z.enum(['allowed', 'allowed-with-attribution', 'denied', 'needs-review']),\n reasons: z.array(z.string()),\n confidence: z.enum(['high', 'low']),\n disclaimer: z.string(),\n attribution: z.object(attributionOutputSchema).optional(),\n },\n },\n async ({ license, licenseVersion, author, title, canonicalUrl, intent, editorialOnly, jurisdiction, userJurisdiction }) => {\n const version = ccVersionFor(license, licenseVersion)\n const rights: RightsRecord = {\n license,\n licenseVersion: version,\n author,\n rehostPolicy: 'cache-allowed',\n jurisdiction,\n editorialOnly,\n raw: { sourceTerms: '', sourceUrl: canonicalUrl },\n }\n const verdict: Verdict = evaluateUse(rights, intent, { userJurisdiction })\n const attribution =\n verdict.decision === 'allowed-with-attribution'\n ? buildAttribution({ license, licenseVersion: version, author, title, canonicalUrl })\n : undefined\n const summary = `${verdict.decision}: ${verdict.reasons.join('; ') || 'license facts allow this use'}`\n return {\n content: [{ type: 'text', text: summary }],\n structuredContent: {\n decision: verdict.decision,\n reasons: verdict.reasons,\n confidence: verdict.confidence,\n disclaimer: verdict.disclaimer,\n ...(attribution ? { attribution } : {}),\n },\n }\n },\n )\n\n server.registerTool(\n 'build_attribution',\n {\n title: 'Build an attribution credit line',\n description:\n 'Mechanically derive an attribution credit line (plain text + HTML) from a license id + author + title + ' +\n 'canonicalUrl. `required` is false when the license needs no attribution (e.g. CC0, PD).',\n inputSchema: {\n license: z.enum(LICENSE_IDS),\n licenseVersion: z.string().optional().describe('precise CC version, e.g. \"4.0\" — appended to the license name'),\n author: z.string().optional(),\n title: z.string().optional(),\n canonicalUrl: z.string(),\n },\n outputSchema: attributionOutputSchema,\n },\n async ({ license, licenseVersion, author, title, canonicalUrl }) => {\n const version = ccVersionFor(license, licenseVersion)\n const attribution: Attribution = buildAttribution({ license, licenseVersion: version, author, title, canonicalUrl })\n return {\n content: [{ type: 'text', text: attribution.required ? (attribution.text ?? '') : 'No attribution required for this license.' }],\n structuredContent: { required: attribution.required, text: attribution.text, html: attribution.html },\n }\n },\n )\n\n return server\n}\n\n/** Run the refkit MCP server over stdio (host wires the RefkitClient + its providers/keys). */\nexport async function serveStdio(refkit: RefkitClient): Promise<void> {\n const server = createRefkitMcpServer(refkit)\n await server.connect(new StdioServerTransport())\n}\n"],"mappings":"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","names":[]}
|