@refkit/mcp 0.7.0 → 0.8.1
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 +11 -6
- package/dist/{chunk-WVJJN6XK.js → chunk-SOL6EG4R.js} +19 -97
- package/dist/chunk-SOL6EG4R.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +21 -21
- package/dist/chunk-WVJJN6XK.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, 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):
|
|
13
|
+
It boots with the keyless sources (Met, Art Institute of Chicago, Wikimedia Commons, Openverse + audio, Project Gutenberg, PoetryDB, Rijksmuseum, Poly Haven, ambientCG, Internet Archive, Nailbook — Japanese nail-art, discovery-class `license: 'unknown'`, best queried with Japanese tag words, and the one source that *declines* queries outside its domain) 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
|
|
@@ -45,13 +45,18 @@ await serveStdio(createRefkit({
|
|
|
45
45
|
|
|
46
46
|
## The `search_references` tool
|
|
47
47
|
|
|
48
|
-
Input: `{ query, modalities?,
|
|
48
|
+
Input: `{ query, modalities?, sources?, controls?, providerOptions?, limit?, cursor?, rerank?, minRelevance?, deadlineMs?, intent?, gateFor?, gateContext?, explain? }`.
|
|
49
49
|
|
|
50
|
-
- `controls` — provider-neutral search controls such as `{ orientation, color, language, sort, safety, license, media }`; providers translate supported controls and report ignored controls when `explain: true`.
|
|
50
|
+
- `controls` — provider-neutral search controls such as `{ orientation, color, language, sort, safety, license, media, page }`; providers translate supported controls and report ignored controls when `explain: true`.
|
|
51
|
+
- `sources` — restrict the search to specific source ids (the ids are listed in the tool description under "Configured sources"). Naming a source also **bypasses** that source's own query-acceptance predicate, so a narrow source like Nailbook — which declines non-nail queries on an unscoped search and then appears as `skipped` with `reason: 'declined'` — still answers when asked for by name.
|
|
52
|
+
- `rerank` — **default true**: results are re-ranked for the query (term coverage incl. CJK over title/description/tags/excerpt, the fused cross-source relevance, resolution, source and near-duplicate diversity). Pass `false` for raw cross-source rank fusion order. `true` cannot re-enable reranking when the host built the client with `rerank: false`.
|
|
53
|
+
- `minRelevance` — drop results the ranker scored below this (0…1), reported as `meta.threshold { minRelevance, dropped }`. The bar is graded against the reranker's *blended* score: under the stock weights a result matching no query term still lands near `0.3` and a full match near `0.95`, so `0.5` is the practical "real matches only" line. It does **not** transfer to `rerank: false`, where max-normalised fusion puts the top result at exactly `1`.
|
|
54
|
+
- `deadlineMs` — bound the whole call (cursor page advances included). Sources still in flight are reported as `failed` and the rest are returned. It is a hard bound while the host leaves per-source resilience on (the default); with resilience disabled it binds only sources that honour the abort signal.
|
|
51
55
|
- `intent` — annotate each result with a **use-verdict** for that intended use (no filtering).
|
|
52
56
|
- `gateFor` — return only results whose license allows that intent.
|
|
53
|
-
- `
|
|
54
|
-
- `
|
|
57
|
+
- `gateContext` — `{ userJurisdiction }` for that gate, matching `evaluate_use`'s jurisdiction input: a source-declared jurisdiction that differs from the caller's defaults to `needs-review`, which `gateFor` then drops.
|
|
58
|
+
- `cursor` — the previous result's top-level `nextCursor` (always returned, no `explain` needed); fetches the next batch, deduped against earlier ones.
|
|
59
|
+
- `explain` — include provider status (incl. per-source `confidence`, `latencyMs`, skip `reason`), applied and ignored unified controls, warnings, and gate/threshold-drop metadata.
|
|
55
60
|
- `providerOptions` — typed provider-specific whitelisted controls keyed by provider id, for example:
|
|
56
61
|
|
|
57
62
|
```json
|
|
@@ -67,7 +72,7 @@ Input: `{ query, modalities?, controls?, filters?, providerOptions?, explain?, l
|
|
|
67
72
|
}
|
|
68
73
|
```
|
|
69
74
|
|
|
70
|
-
Output: `{ references: [{ id, title?, modality, provider, canonicalUrl, license, thumbnail?, excerpt?, useVerdict?, useExplanation?, attribution? }], meta? }`. When `intent` (or `gateFor`) is set, each result carries `useVerdict { decision, reason, confidence }`, a plain `useExplanation`, and — if the license requires it — a ready-to-use `attribution` credit line. When `explain: true`, `meta` includes per-provider `fulfilled` / `failed` / `skipped` status, applied/ignored control details, warnings, and gate/drop counts.
|
|
75
|
+
Output: `{ references: [{ id, title?, modality, kind?, provider, canonicalUrl, license, thumbnail?, excerpt?, useVerdict?, useExplanation?, attribution? }], nextCursor?, meta? }`. When `intent` (or `gateFor`) is set, each result carries `useVerdict { decision, reason, confidence }`, a plain `useExplanation`, and — if the license requires it — a ready-to-use `attribution` credit line. When `explain: true`, `meta` includes per-provider `fulfilled` / `failed` / `skipped` status, applied/ignored control details, warnings, and gate/threshold-drop counts. The `meta` shape comes from core's own `searchMetaSchema` — this server keeps no copy of the vocabulary.
|
|
71
76
|
|
|
72
77
|
> Results are references with a license id + source link — **not rights clearance, not legal advice**. `unknown` / `needs-review` results require the caller to verify the source's terms.
|
|
73
78
|
|
|
@@ -3,64 +3,8 @@ import { readFileSync } from "fs";
|
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { LICENSE_IDS, INTENTS, evaluateUse, buildAttribution, ccVersionFor,
|
|
7
|
-
var MODALITIES = ["image", "video", "audio", "text"];
|
|
8
|
-
var ORIENTATIONS = ["landscape", "portrait", "square"];
|
|
6
|
+
import { LICENSE_IDS, INTENTS, evaluateUse, buildAttribution, ccVersionFor, buildSearchControlsSchema, searchMetaSchema } from "@refkit/core";
|
|
9
7
|
var BASE_MEDIA_KINDS = ["photo", "illustration", "vector", "film", "animation"];
|
|
10
|
-
var SEARCH_CONTROL_KEYS = [
|
|
11
|
-
"orientation",
|
|
12
|
-
"color",
|
|
13
|
-
"language",
|
|
14
|
-
"sort",
|
|
15
|
-
"safety",
|
|
16
|
-
"license.commercial",
|
|
17
|
-
"license.modification",
|
|
18
|
-
"license.allowUnknown",
|
|
19
|
-
"media.kind",
|
|
20
|
-
"media.size",
|
|
21
|
-
"media.minWidth",
|
|
22
|
-
"media.minHeight",
|
|
23
|
-
"media.duration",
|
|
24
|
-
"creator.id",
|
|
25
|
-
"creator.name",
|
|
26
|
-
"text.copyright",
|
|
27
|
-
"page"
|
|
28
|
-
];
|
|
29
|
-
var filtersSchema = z.object({
|
|
30
|
-
color: z.string().optional(),
|
|
31
|
-
orientation: z.enum(ORIENTATIONS).optional(),
|
|
32
|
-
language: z.string().optional()
|
|
33
|
-
});
|
|
34
|
-
var searchControlKeySchema = z.enum(SEARCH_CONTROL_KEYS);
|
|
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
|
-
}
|
|
64
8
|
var providerOptionValueSchema = z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]);
|
|
65
9
|
var providerOptionsSchema = z.record(z.string(), z.record(z.string(), providerOptionValueSchema));
|
|
66
10
|
var VERSION = (() => {
|
|
@@ -107,39 +51,6 @@ var agentRefSchema = z.object({
|
|
|
107
51
|
useExplanation: z.string().optional().describe("plain-language use verdict summary for agents"),
|
|
108
52
|
attribution: z.string().optional().describe("ready-to-use credit line; present when the license requires attribution")
|
|
109
53
|
});
|
|
110
|
-
var searchMetaSchema = z.object({
|
|
111
|
-
query: z.string(),
|
|
112
|
-
modalities: z.array(z.enum(MODALITIES)),
|
|
113
|
-
limit: z.number(),
|
|
114
|
-
poolFactor: z.number(),
|
|
115
|
-
fetchLimit: z.number(),
|
|
116
|
-
appliedFilters: filtersSchema.optional(),
|
|
117
|
-
controls: z.object({
|
|
118
|
-
requested: z.array(searchControlKeySchema),
|
|
119
|
-
appliedByProvider: z.record(z.string(), z.array(searchControlKeySchema)),
|
|
120
|
-
ignoredByProvider: z.record(z.string(), z.array(searchControlKeySchema))
|
|
121
|
-
}).optional(),
|
|
122
|
-
providerOptions: z.array(z.string()).optional(),
|
|
123
|
-
providers: z.array(z.object({
|
|
124
|
-
providerId: z.string(),
|
|
125
|
-
status: z.enum(["fulfilled", "failed", "skipped"]),
|
|
126
|
-
returned: z.number().optional(),
|
|
127
|
-
accepted: z.number().optional(),
|
|
128
|
-
rejected: z.number().optional(),
|
|
129
|
-
reason: z.enum(["unsupported-modality", "unsupported-kind", "not-selected"]).optional(),
|
|
130
|
-
error: z.string().optional(),
|
|
131
|
-
latencyMs: z.number().optional(),
|
|
132
|
-
cached: z.boolean().optional()
|
|
133
|
-
})),
|
|
134
|
-
gate: z.object({
|
|
135
|
-
intent: z.enum(INTENTS),
|
|
136
|
-
before: z.number(),
|
|
137
|
-
after: z.number(),
|
|
138
|
-
dropped: z.number()
|
|
139
|
-
}).optional(),
|
|
140
|
-
nextCursor: z.string().optional().describe("opaque load-more cursor; pass back as `cursor` to fetch the next page with cross-page dedup"),
|
|
141
|
-
warnings: z.array(z.string())
|
|
142
|
-
});
|
|
143
54
|
function createRefkitMcpServer(refkit) {
|
|
144
55
|
const server = new McpServer({ name: "refkit", version: VERSION });
|
|
145
56
|
const enabledSourceIds = refkit.providers.map((p) => p.id);
|
|
@@ -163,13 +74,21 @@ function createRefkitMcpServer(refkit) {
|
|
|
163
74
|
sources: z.array(z.string()).optional().describe(
|
|
164
75
|
`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
76
|
),
|
|
166
|
-
filters: filtersSchema.optional().describe("compatibility alias for controls.orientation, controls.color, and controls.language"),
|
|
167
77
|
controls: searchControlsSchema.optional().describe("provider-neutral search controls; providers translate supported controls and report ignored controls in explain metadata"),
|
|
168
78
|
providerOptions: providerOptionsSchema.optional().describe("provider-specific search controls keyed by provider id; each provider whitelists supported keys"),
|
|
169
79
|
explain: z.boolean().optional().describe("include provider status, applied and ignored controls, warnings, gate/drop metadata, and the load-more cursor"),
|
|
170
80
|
limit: z.number().int().positive().optional(),
|
|
171
81
|
cursor: z.string().optional().describe("opaque cursor from a previous result's nextCursor \u2014 fetches the next batch, deduped against earlier batches"),
|
|
172
|
-
rerank: z.boolean().optional().describe("re-rank results by query relevance (term coverage incl. CJK, resolution, source diversity)
|
|
82
|
+
rerank: z.boolean().optional().describe("re-rank results by query relevance (term coverage incl. CJK over title/description/tags/excerpt, fused cross-source relevance, resolution, source and near-duplicate diversity). Default true \u2014 pass false for raw cross-source rank fusion. true cannot re-enable reranking when the host built the client with rerank: false"),
|
|
83
|
+
minRelevance: z.number().min(0).max(1).optional().describe(
|
|
84
|
+
"drop results the ranker scored below this, after reranking. Graded against the reranker's blended score, where a result matching no query term lands around 0.3 under the stock weights \u2014 so 0.5 keeps only real matches. Off by default (a bar can empty the batch). Does NOT transfer to rerank: false, where raw fusion is max-normalised and the top result is always 1"
|
|
85
|
+
),
|
|
86
|
+
deadlineMs: z.number().int().positive().optional().describe(
|
|
87
|
+
"whole-search deadline in ms, cursor page advances included (unlike the host's per-source timeout, which bounds one source search). Sources still in flight when it fires are reported as failed and the rest are returned; a hard bound while the host leaves per-source resilience on (the default), and otherwise only binding on sources that honour the abort signal"
|
|
88
|
+
),
|
|
89
|
+
gateContext: z.object({
|
|
90
|
+
userJurisdiction: z.string().optional().describe("caller's jurisdiction; a mismatch with a source-declared one defaults to needs-review")
|
|
91
|
+
}).optional().describe("context for the `gateFor` gate, matching the evaluate_use tool's jurisdiction inputs"),
|
|
173
92
|
intent: z.enum(INTENTS).optional().describe("annotate each result with a use-verdict for this intended use (no filtering)"),
|
|
174
93
|
gateFor: z.enum(INTENTS).optional().describe("only return results whose license allows this intended use")
|
|
175
94
|
},
|
|
@@ -179,18 +98,21 @@ function createRefkitMcpServer(refkit) {
|
|
|
179
98
|
meta: searchMetaSchema.optional()
|
|
180
99
|
}
|
|
181
100
|
},
|
|
182
|
-
async ({ query, modalities,
|
|
101
|
+
async ({ query, modalities, controls, providerOptions, explain, limit, cursor, rerank, minRelevance, deadlineMs, gateContext, intent, gateFor, sources }) => {
|
|
183
102
|
const searchInput = {
|
|
184
103
|
query,
|
|
185
104
|
modalities: modalities ?? ["image"],
|
|
186
105
|
sources,
|
|
187
|
-
filters,
|
|
188
106
|
controls,
|
|
189
107
|
providerOptions,
|
|
190
108
|
limit,
|
|
191
109
|
cursor,
|
|
192
|
-
|
|
193
|
-
|
|
110
|
+
// Core reranks by default; only an explicit false turns it off.
|
|
111
|
+
...rerank === false ? { rerank: false } : {},
|
|
112
|
+
minRelevance,
|
|
113
|
+
deadlineMs,
|
|
114
|
+
gateFor,
|
|
115
|
+
gateContext
|
|
194
116
|
};
|
|
195
117
|
let result;
|
|
196
118
|
try {
|
|
@@ -306,4 +228,4 @@ export {
|
|
|
306
228
|
createRefkitMcpServer,
|
|
307
229
|
serveStdio
|
|
308
230
|
};
|
|
309
|
-
//# sourceMappingURL=chunk-
|
|
231
|
+
//# sourceMappingURL=chunk-SOL6EG4R.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, buildSearchControlsSchema, searchMetaSchema } from '@refkit/core'\nimport type { RefkitClient, Reference, Verdict, Attribution, SearchControls, SearchInput, ProviderOptionsById, RightsRecord, Modality } from '@refkit/core'\n\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\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\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 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 over title/description/tags/excerpt, fused cross-source relevance, resolution, source and near-duplicate diversity). Default true — pass false for raw cross-source rank fusion. true cannot re-enable reranking when the host built the client with rerank: false'),\n minRelevance: z.number().min(0).max(1).optional().describe(\n 'drop results the ranker scored below this, after reranking. Graded against the reranker\\'s blended score, where a result matching no query term lands around 0.3 under the stock weights — so 0.5 keeps only real matches. Off by default (a bar can empty the batch). Does NOT transfer to rerank: false, where raw fusion is max-normalised and the top result is always 1',\n ),\n deadlineMs: z.number().int().positive().optional().describe(\n 'whole-search deadline in ms, cursor page advances included (unlike the host\\'s per-source timeout, which bounds one source search). Sources still in flight when it fires are reported as failed and the rest are returned; a hard bound while the host leaves per-source resilience on (the default), and otherwise only binding on sources that honour the abort signal',\n ),\n gateContext: z.object({\n userJurisdiction: z.string().optional().describe('caller\\'s jurisdiction; a mismatch with a source-declared one defaults to needs-review'),\n }).optional().describe('context for the `gateFor` gate, matching the evaluate_use tool\\'s jurisdiction inputs'),\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, controls, providerOptions, explain, limit, cursor, rerank, minRelevance, deadlineMs, gateContext, intent, gateFor, sources }) => {\n // Typed as core's SearchInput so every parameter above is checked against\n // the contract it is forwarded into, not just against zod.\n const searchInput: SearchInput = {\n query,\n modalities: modalities ?? ['image'],\n sources,\n controls: controls as SearchControls | undefined,\n providerOptions: providerOptions as ProviderOptionsById | undefined,\n limit,\n cursor,\n // Core reranks by default; only an explicit false turns it off.\n ...(rerank === false ? { rerank: false as const } : {}),\n minRelevance,\n deadlineMs,\n gateFor,\n gateContext,\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.js
CHANGED
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.8.1",
|
|
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,32 +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-
|
|
39
|
-
"@refkit/provider-
|
|
40
|
-
"@refkit/provider-
|
|
41
|
-
"@refkit/provider-met": "0.
|
|
42
|
-
"@refkit/provider-nailbook": "0.
|
|
43
|
-
"@refkit/provider-openverse": "0.
|
|
44
|
-
"@refkit/provider-poetrydb": "0.
|
|
45
|
-
"@refkit/provider-polyhaven": "0.
|
|
46
|
-
"@refkit/provider-rijksmuseum": "0.
|
|
47
|
-
"@refkit/provider-wikimedia-commons": "0.
|
|
37
|
+
"@refkit/core": "0.9.0",
|
|
38
|
+
"@refkit/provider-gutendex": "0.4.0",
|
|
39
|
+
"@refkit/provider-internet-archive": "0.5.0",
|
|
40
|
+
"@refkit/provider-artic": "0.4.1",
|
|
41
|
+
"@refkit/provider-met": "0.4.0",
|
|
42
|
+
"@refkit/provider-nailbook": "0.2.0",
|
|
43
|
+
"@refkit/provider-openverse": "0.5.1",
|
|
44
|
+
"@refkit/provider-poetrydb": "0.4.0",
|
|
45
|
+
"@refkit/provider-polyhaven": "0.4.0",
|
|
46
|
+
"@refkit/provider-rijksmuseum": "0.4.0",
|
|
47
|
+
"@refkit/provider-wikimedia-commons": "0.5.0"
|
|
48
48
|
},
|
|
49
49
|
"files": [
|
|
50
50
|
"dist",
|
|
51
51
|
"LICENSE"
|
|
52
52
|
],
|
|
53
53
|
"optionalDependencies": {
|
|
54
|
-
"@refkit/provider-
|
|
55
|
-
"@refkit/provider-
|
|
56
|
-
"@refkit/provider-
|
|
57
|
-
"@refkit/provider-
|
|
58
|
-
"@refkit/provider-
|
|
59
|
-
"@refkit/provider-pixabay": "0.
|
|
60
|
-
"@refkit/provider-smithsonian": "0.
|
|
61
|
-
"@refkit/provider-
|
|
62
|
-
"@refkit/provider-
|
|
54
|
+
"@refkit/provider-brave": "0.4.0",
|
|
55
|
+
"@refkit/provider-europeana": "0.5.0",
|
|
56
|
+
"@refkit/provider-flickr": "0.5.0",
|
|
57
|
+
"@refkit/provider-pexels": "0.4.0",
|
|
58
|
+
"@refkit/provider-freesound": "0.5.0",
|
|
59
|
+
"@refkit/provider-pixabay": "0.4.0",
|
|
60
|
+
"@refkit/provider-smithsonian": "0.4.0",
|
|
61
|
+
"@refkit/provider-unsplash": "0.4.0",
|
|
62
|
+
"@refkit/provider-jamendo": "0.5.0"
|
|
63
63
|
},
|
|
64
64
|
"scripts": {
|
|
65
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, 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":[]}
|