@refkit/mcp 0.1.1 → 0.3.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 +48 -9
- package/dist/chunk-B5SVJVI4.js +188 -0
- package/dist/chunk-B5SVJVI4.js.map +1 -0
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +54 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.js +4 -58
- package/dist/index.js.map +1 -1
- package/package.json +17 -5
package/README.md
CHANGED
|
@@ -2,7 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
An MCP server that exposes refkit's **license-normalized reference search** as an agent tool (`search_references`).
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Zero-config (`npx`)
|
|
6
|
+
|
|
7
|
+
Point any MCP client at:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx -y @refkit/mcp
|
|
11
|
+
```
|
|
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:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
UNSPLASH_KEY=… PEXELS_KEY=… PIXABAY_KEY=… FLICKR_KEY=… SI_KEY=… BRAVE_TOKEN=… npx -y @refkit/mcp
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Example MCP client config:
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{ "mcpServers": { "refkit": { "command": "npx", "args": ["-y", "@refkit/mcp"] } } }
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Programmatic (bring your own providers)
|
|
6
26
|
|
|
7
27
|
The host owns wiring — which providers, which BYOK keys — and passes a configured `RefkitClient`:
|
|
8
28
|
|
|
@@ -11,21 +31,40 @@ import { serveStdio } from '@refkit/mcp'
|
|
|
11
31
|
import { createRefkit } from '@refkit/core'
|
|
12
32
|
import { openverse } from '@refkit/provider-openverse'
|
|
13
33
|
import { unsplash } from '@refkit/provider-unsplash'
|
|
14
|
-
import { gutendex } from '@refkit/provider-gutendex'
|
|
15
34
|
|
|
16
35
|
await serveStdio(createRefkit({
|
|
17
|
-
providers: [
|
|
18
|
-
openverse(), // keyless
|
|
19
|
-
unsplash({ accessKey: process.env.UNSPLASH_KEY! }),
|
|
20
|
-
gutendex(),
|
|
21
|
-
],
|
|
36
|
+
providers: [openverse(), unsplash({ accessKey: process.env.UNSPLASH_KEY! })],
|
|
22
37
|
// fetch defaults to globalThis.fetch
|
|
23
38
|
}))
|
|
24
39
|
```
|
|
25
40
|
|
|
26
|
-
|
|
41
|
+
## The `search_references` tool
|
|
42
|
+
|
|
43
|
+
Input: `{ query, modalities?, controls?, filters?, providerOptions?, explain?, limit?, intent?, gateFor? }`.
|
|
44
|
+
|
|
45
|
+
- `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`.
|
|
46
|
+
- `intent` — annotate each result with a **use-verdict** for that intended use (no filtering).
|
|
47
|
+
- `gateFor` — return only results whose license allows that intent.
|
|
48
|
+
- `filters` — compatibility alias for `controls.orientation`, `controls.color`, and `controls.language`.
|
|
49
|
+
- `explain` — include provider status, applied and ignored unified controls, warnings, and gate/drop metadata.
|
|
50
|
+
- `providerOptions` — typed provider-specific whitelisted controls keyed by provider id, for example:
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"query": "forest path",
|
|
55
|
+
"modalities": ["image"],
|
|
56
|
+
"controls": { "orientation": "landscape", "color": "green", "safety": "strict" },
|
|
57
|
+
"providerOptions": {
|
|
58
|
+
"unsplash": { "collections": ["abc", "def"], "page": 2 },
|
|
59
|
+
"flickr": { "tags": ["forest", "path"], "tagMode": "all", "minTakenDate": "2020-01-01" },
|
|
60
|
+
"brave": { "country": "US", "searchLang": "en" }
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
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.
|
|
27
66
|
|
|
28
|
-
> Results are references with a license id + source link — **not rights clearance, not legal advice**. `unknown
|
|
67
|
+
> 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.
|
|
29
68
|
|
|
30
69
|
## Discovery (web) source
|
|
31
70
|
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
var MODALITIES = ["image", "video", "audio", "text"];
|
|
7
|
+
var INTENTS = ["internal-moodboard", "commercial-product", "ai-generation-input", "redistribution"];
|
|
8
|
+
var ORIENTATIONS = ["landscape", "portrait", "square"];
|
|
9
|
+
var SEARCH_CONTROL_KEYS = [
|
|
10
|
+
"orientation",
|
|
11
|
+
"color",
|
|
12
|
+
"language",
|
|
13
|
+
"sort",
|
|
14
|
+
"safety",
|
|
15
|
+
"license.commercial",
|
|
16
|
+
"license.modification",
|
|
17
|
+
"license.allowUnknown",
|
|
18
|
+
"media.kind",
|
|
19
|
+
"media.size",
|
|
20
|
+
"media.minWidth",
|
|
21
|
+
"media.minHeight",
|
|
22
|
+
"media.duration",
|
|
23
|
+
"creator.id",
|
|
24
|
+
"creator.name",
|
|
25
|
+
"text.copyright",
|
|
26
|
+
"page"
|
|
27
|
+
];
|
|
28
|
+
var filtersSchema = z.object({
|
|
29
|
+
color: z.string().optional(),
|
|
30
|
+
orientation: z.enum(ORIENTATIONS).optional(),
|
|
31
|
+
language: z.string().optional()
|
|
32
|
+
});
|
|
33
|
+
var searchControlKeySchema = z.enum(SEARCH_CONTROL_KEYS);
|
|
34
|
+
var searchControlsSchema = z.object({
|
|
35
|
+
orientation: z.enum(ORIENTATIONS).optional(),
|
|
36
|
+
color: z.string().optional(),
|
|
37
|
+
language: z.string().optional(),
|
|
38
|
+
sort: z.enum(["relevance", "latest", "popular", "interesting"]).optional(),
|
|
39
|
+
safety: z.enum(["strict", "moderate", "off"]).optional(),
|
|
40
|
+
license: z.object({
|
|
41
|
+
commercial: z.boolean().optional(),
|
|
42
|
+
modification: z.boolean().optional(),
|
|
43
|
+
allowUnknown: z.boolean().optional()
|
|
44
|
+
}).optional(),
|
|
45
|
+
media: z.object({
|
|
46
|
+
kind: z.enum(["photo", "illustration", "vector", "film", "animation"]).optional(),
|
|
47
|
+
size: z.enum(["small", "medium", "large"]).optional(),
|
|
48
|
+
minWidth: z.number().int().nonnegative().optional(),
|
|
49
|
+
minHeight: z.number().int().nonnegative().optional(),
|
|
50
|
+
duration: z.enum(["short", "medium", "long"]).optional()
|
|
51
|
+
}).optional(),
|
|
52
|
+
creator: z.object({
|
|
53
|
+
id: z.string().optional(),
|
|
54
|
+
name: z.string().optional()
|
|
55
|
+
}).optional(),
|
|
56
|
+
text: z.object({
|
|
57
|
+
copyright: z.enum(["public-domain", "copyrighted", "any"]).optional()
|
|
58
|
+
}).optional(),
|
|
59
|
+
page: z.number().int().positive().optional()
|
|
60
|
+
});
|
|
61
|
+
var providerOptionValueSchema = z.union([z.string(), z.number(), z.boolean(), z.array(z.string())]);
|
|
62
|
+
var providerOptionsSchema = z.record(z.string(), z.record(z.string(), providerOptionValueSchema));
|
|
63
|
+
var VERSION = (() => {
|
|
64
|
+
try {
|
|
65
|
+
return JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
66
|
+
} catch {
|
|
67
|
+
return "0.0.0";
|
|
68
|
+
}
|
|
69
|
+
})();
|
|
70
|
+
function toAgentRef(r, assessment) {
|
|
71
|
+
const base = {
|
|
72
|
+
id: r.id,
|
|
73
|
+
title: r.title,
|
|
74
|
+
modality: r.modality,
|
|
75
|
+
provider: r.source.providerId,
|
|
76
|
+
canonicalUrl: r.canonicalUrl,
|
|
77
|
+
license: r.rights.license,
|
|
78
|
+
thumbnail: r.thumbnail?.url,
|
|
79
|
+
excerpt: r.text?.excerpt
|
|
80
|
+
};
|
|
81
|
+
if (!assessment) return base;
|
|
82
|
+
const { verdict, attribution } = assessment;
|
|
83
|
+
const reason = verdict.reasons.join("; ");
|
|
84
|
+
const useExplanation = `${verdict.decision}: ${reason || "license facts allow this use"}${attribution.required && attribution.text ? ` Attribution required: ${attribution.text}` : ""}`;
|
|
85
|
+
return {
|
|
86
|
+
...base,
|
|
87
|
+
useVerdict: { decision: verdict.decision, reason: verdict.reasons.join("; "), confidence: verdict.confidence },
|
|
88
|
+
useExplanation,
|
|
89
|
+
...attribution.required && attribution.text ? { attribution: attribution.text } : {}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
var agentRefSchema = z.object({
|
|
93
|
+
id: z.string(),
|
|
94
|
+
title: z.string().optional(),
|
|
95
|
+
modality: z.string(),
|
|
96
|
+
provider: z.string(),
|
|
97
|
+
canonicalUrl: z.string(),
|
|
98
|
+
license: z.string(),
|
|
99
|
+
thumbnail: z.string().optional(),
|
|
100
|
+
excerpt: z.string().optional(),
|
|
101
|
+
useVerdict: z.object({ decision: z.string(), reason: z.string(), confidence: z.string() }).optional().describe("present when `intent` (or `gateFor`) is set: may this be used for that intent, and how confident"),
|
|
102
|
+
useExplanation: z.string().optional().describe("plain-language use verdict summary for agents"),
|
|
103
|
+
attribution: z.string().optional().describe("ready-to-use credit line; present when the license requires attribution")
|
|
104
|
+
});
|
|
105
|
+
var searchMetaSchema = z.object({
|
|
106
|
+
query: z.string(),
|
|
107
|
+
modalities: z.array(z.enum(MODALITIES)),
|
|
108
|
+
limit: z.number(),
|
|
109
|
+
poolFactor: z.number(),
|
|
110
|
+
fetchLimit: z.number(),
|
|
111
|
+
appliedFilters: filtersSchema.optional(),
|
|
112
|
+
controls: z.object({
|
|
113
|
+
requested: z.array(searchControlKeySchema),
|
|
114
|
+
appliedByProvider: z.record(z.string(), z.array(searchControlKeySchema)),
|
|
115
|
+
ignoredByProvider: z.record(z.string(), z.array(searchControlKeySchema))
|
|
116
|
+
}).optional(),
|
|
117
|
+
providerOptions: z.array(z.string()).optional(),
|
|
118
|
+
providers: z.array(z.object({
|
|
119
|
+
providerId: z.string(),
|
|
120
|
+
status: z.enum(["fulfilled", "failed", "skipped"]),
|
|
121
|
+
returned: z.number().optional(),
|
|
122
|
+
accepted: z.number().optional(),
|
|
123
|
+
rejected: z.number().optional(),
|
|
124
|
+
reason: z.enum(["unsupported-modality"]).optional(),
|
|
125
|
+
error: z.string().optional()
|
|
126
|
+
})),
|
|
127
|
+
gate: z.object({
|
|
128
|
+
intent: z.enum(INTENTS),
|
|
129
|
+
before: z.number(),
|
|
130
|
+
after: z.number(),
|
|
131
|
+
dropped: z.number()
|
|
132
|
+
}).optional(),
|
|
133
|
+
warnings: z.array(z.string())
|
|
134
|
+
});
|
|
135
|
+
function createRefkitMcpServer(refkit) {
|
|
136
|
+
const server = new McpServer({ name: "refkit", version: VERSION });
|
|
137
|
+
server.registerTool(
|
|
138
|
+
"search_references",
|
|
139
|
+
{
|
|
140
|
+
title: "Search creative references",
|
|
141
|
+
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.",
|
|
142
|
+
inputSchema: {
|
|
143
|
+
query: z.string().describe('what to search for, e.g. "cyberpunk alley at night"'),
|
|
144
|
+
modalities: z.array(z.enum(MODALITIES)).optional().describe('default ["image"]'),
|
|
145
|
+
filters: filtersSchema.optional().describe("compatibility alias for controls.orientation, controls.color, and controls.language"),
|
|
146
|
+
controls: searchControlsSchema.optional().describe("provider-neutral search controls; providers translate supported controls and report ignored controls in explain metadata"),
|
|
147
|
+
providerOptions: providerOptionsSchema.optional().describe("provider-specific search controls keyed by provider id; each provider whitelists supported keys"),
|
|
148
|
+
explain: z.boolean().optional().describe("include provider status, applied and ignored controls, warnings, and gate/drop metadata"),
|
|
149
|
+
limit: z.number().int().positive().optional(),
|
|
150
|
+
intent: z.enum(INTENTS).optional().describe("annotate each result with a use-verdict for this intended use (no filtering)"),
|
|
151
|
+
gateFor: z.enum(INTENTS).optional().describe("only return results whose license allows this intended use")
|
|
152
|
+
},
|
|
153
|
+
outputSchema: { references: z.array(agentRefSchema), meta: searchMetaSchema.optional() }
|
|
154
|
+
},
|
|
155
|
+
async ({ query, modalities, filters, controls, providerOptions, explain, limit, intent, gateFor }) => {
|
|
156
|
+
const searchInput = {
|
|
157
|
+
query,
|
|
158
|
+
modalities: modalities ?? ["image"],
|
|
159
|
+
filters,
|
|
160
|
+
controls,
|
|
161
|
+
providerOptions,
|
|
162
|
+
limit,
|
|
163
|
+
gateFor
|
|
164
|
+
};
|
|
165
|
+
const result = explain ? await refkit.searchWithMeta(searchInput) : { references: await refkit.search(searchInput), meta: void 0 };
|
|
166
|
+
const refs = result.references;
|
|
167
|
+
const assessIntent = intent ?? gateFor;
|
|
168
|
+
const references = refs.map(
|
|
169
|
+
(r) => assessIntent ? toAgentRef(r, { verdict: refkit.evaluateUse(r, assessIntent), attribution: refkit.buildAttribution(r) }) : toAgentRef(r)
|
|
170
|
+
);
|
|
171
|
+
return {
|
|
172
|
+
content: [{ type: "text", text: `${references.length} reference(s) for "${query}".` }],
|
|
173
|
+
structuredContent: { references, ...result.meta ? { meta: result.meta } : {} }
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
);
|
|
177
|
+
return server;
|
|
178
|
+
}
|
|
179
|
+
async function serveStdio(refkit) {
|
|
180
|
+
const server = createRefkitMcpServer(refkit);
|
|
181
|
+
await server.connect(new StdioServerTransport());
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
createRefkitMcpServer,
|
|
186
|
+
serveStdio
|
|
187
|
+
};
|
|
188
|
+
//# sourceMappingURL=chunk-B5SVJVI4.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 type { RefkitClient, Reference, Verdict, Attribution, SearchFilters, SearchControls, SearchControlKey, ProviderOptionsById, SearchMeta } from '@refkit/core'\n\nconst MODALITIES = ['image', 'video', 'audio', 'text'] as const\nconst INTENTS = ['internal-moodboard', 'commercial-product', 'ai-generation-input', 'redistribution'] 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 })),\n gate: z.object({\n intent: z.enum(INTENTS),\n before: z.number(),\n after: z.number(),\n dropped: z.number(),\n }).optional(),\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, and gate/drop metadata'),\n limit: z.number().int().positive().optional(),\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: { references: z.array(agentRefSchema), meta: searchMetaSchema.optional() },\n },\n async ({ query, modalities, filters, controls, providerOptions, explain, limit, 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 gateFor,\n }\n const result = explain ? await refkit.searchWithMeta(searchInput) : { references: await refkit.search(searchInput), meta: undefined }\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: { references, ...(result.meta ? { meta: result.meta } : {}) },\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
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { ReferenceProvider } from '@refkit/core';
|
|
3
|
+
|
|
4
|
+
/** Providers a zero-config server boots with: all keyless sources, plus any BYOK
|
|
5
|
+
* source whose key is present in `env`. Exported so the wiring is unit-testable. */
|
|
6
|
+
declare function defaultProviders(env?: NodeJS.ProcessEnv): ReferenceProvider[];
|
|
7
|
+
|
|
8
|
+
export { defaultProviders };
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
serveStdio
|
|
4
|
+
} from "./chunk-B5SVJVI4.js";
|
|
5
|
+
|
|
6
|
+
// src/cli.ts
|
|
7
|
+
import { realpathSync } from "fs";
|
|
8
|
+
import { fileURLToPath } from "url";
|
|
9
|
+
import { createRefkit } from "@refkit/core";
|
|
10
|
+
import { openverse, openverseAudio } from "@refkit/provider-openverse";
|
|
11
|
+
import { wikimediaCommons } from "@refkit/provider-wikimedia-commons";
|
|
12
|
+
import { met } from "@refkit/provider-met";
|
|
13
|
+
import { artic } from "@refkit/provider-artic";
|
|
14
|
+
import { gutendex } from "@refkit/provider-gutendex";
|
|
15
|
+
import { poetrydb } from "@refkit/provider-poetrydb";
|
|
16
|
+
import { unsplash } from "@refkit/provider-unsplash";
|
|
17
|
+
import { pexels, pexelsVideo } from "@refkit/provider-pexels";
|
|
18
|
+
import { pixabay, pixabayVideo } from "@refkit/provider-pixabay";
|
|
19
|
+
import { flickr } from "@refkit/provider-flickr";
|
|
20
|
+
import { smithsonian } from "@refkit/provider-smithsonian";
|
|
21
|
+
import { brave } from "@refkit/provider-brave";
|
|
22
|
+
function defaultProviders(env = process.env) {
|
|
23
|
+
const providers = [
|
|
24
|
+
openverse(),
|
|
25
|
+
openverseAudio(),
|
|
26
|
+
wikimediaCommons(),
|
|
27
|
+
met(),
|
|
28
|
+
artic(),
|
|
29
|
+
gutendex(),
|
|
30
|
+
poetrydb()
|
|
31
|
+
];
|
|
32
|
+
if (env.UNSPLASH_KEY) providers.push(unsplash({ accessKey: env.UNSPLASH_KEY }));
|
|
33
|
+
if (env.PEXELS_KEY) providers.push(pexels({ apiKey: env.PEXELS_KEY }), pexelsVideo({ apiKey: env.PEXELS_KEY }));
|
|
34
|
+
if (env.PIXABAY_KEY) providers.push(pixabay({ key: env.PIXABAY_KEY }), pixabayVideo({ key: env.PIXABAY_KEY }));
|
|
35
|
+
if (env.FLICKR_KEY) providers.push(flickr({ apiKey: env.FLICKR_KEY }));
|
|
36
|
+
if (env.SI_KEY) providers.push(smithsonian({ apiKey: env.SI_KEY }));
|
|
37
|
+
if (env.BRAVE_TOKEN) providers.push(brave({ token: env.BRAVE_TOKEN }));
|
|
38
|
+
return providers;
|
|
39
|
+
}
|
|
40
|
+
var isEntry = (() => {
|
|
41
|
+
if (!process.argv[1]) return false;
|
|
42
|
+
try {
|
|
43
|
+
return realpathSync(process.argv[1]) === fileURLToPath(import.meta.url);
|
|
44
|
+
} catch {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
})();
|
|
48
|
+
if (isEntry) {
|
|
49
|
+
await serveStdio(createRefkit({ providers: defaultProviders() }));
|
|
50
|
+
}
|
|
51
|
+
export {
|
|
52
|
+
defaultProviders
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +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 { unsplash } from '@refkit/provider-unsplash'\nimport { pexels, pexelsVideo } from '@refkit/provider-pexels'\nimport { pixabay, pixabayVideo } from '@refkit/provider-pixabay'\nimport { flickr } from '@refkit/provider-flickr'\nimport { smithsonian } from '@refkit/provider-smithsonian'\nimport { brave } from '@refkit/provider-brave'\nimport { serveStdio } from './index'\n\n/** Providers a zero-config server boots with: all keyless sources, plus any BYOK\n * source whose key is present in `env`. Exported so the wiring is unit-testable. */\nexport function defaultProviders(env: NodeJS.ProcessEnv = process.env): ReferenceProvider[] {\n const providers: ReferenceProvider[] = [\n openverse(), openverseAudio(), wikimediaCommons(), met(), artic(), gutendex(), poetrydb(),\n ]\n if (env.UNSPLASH_KEY) providers.push(unsplash({ accessKey: env.UNSPLASH_KEY }))\n if (env.PEXELS_KEY) providers.push(pexels({ apiKey: env.PEXELS_KEY }), pexelsVideo({ apiKey: env.PEXELS_KEY }))\n if (env.PIXABAY_KEY) providers.push(pixabay({ key: env.PIXABAY_KEY }), pixabayVideo({ key: env.PIXABAY_KEY }))\n if (env.FLICKR_KEY) providers.push(flickr({ apiKey: env.FLICKR_KEY }))\n if (env.SI_KEY) providers.push(smithsonian({ apiKey: env.SI_KEY }))\n if (env.BRAVE_TOKEN) providers.push(brave({ token: env.BRAVE_TOKEN }))\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: defaultProviders() }))\n}\n"],"mappings":";;;;;;AAGA,SAAS,oBAAoB;AAC7B,SAAS,qBAAqB;AAC9B,SAAS,oBAA4C;AACrD,SAAS,WAAW,sBAAsB;AAC1C,SAAS,wBAAwB;AACjC,SAAS,WAAW;AACpB,SAAS,aAAa;AACtB,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,gBAAgB;AACzB,SAAS,QAAQ,mBAAmB;AACpC,SAAS,SAAS,oBAAoB;AACtC,SAAS,cAAc;AACvB,SAAS,mBAAmB;AAC5B,SAAS,aAAa;AAKf,SAAS,iBAAiB,MAAyB,QAAQ,KAA0B;AAC1F,QAAM,YAAiC;AAAA,IACrC,UAAU;AAAA,IAAG,eAAe;AAAA,IAAG,iBAAiB;AAAA,IAAG,IAAI;AAAA,IAAG,MAAM;AAAA,IAAG,SAAS;AAAA,IAAG,SAAS;AAAA,EAC1F;AACA,MAAI,IAAI,aAAc,WAAU,KAAK,SAAS,EAAE,WAAW,IAAI,aAAa,CAAC,CAAC;AAC9E,MAAI,IAAI,WAAY,WAAU,KAAK,OAAO,EAAE,QAAQ,IAAI,WAAW,CAAC,GAAG,YAAY,EAAE,QAAQ,IAAI,WAAW,CAAC,CAAC;AAC9G,MAAI,IAAI,YAAa,WAAU,KAAK,QAAQ,EAAE,KAAK,IAAI,YAAY,CAAC,GAAG,aAAa,EAAE,KAAK,IAAI,YAAY,CAAC,CAAC;AAC7G,MAAI,IAAI,WAAY,WAAU,KAAK,OAAO,EAAE,QAAQ,IAAI,WAAW,CAAC,CAAC;AACrE,MAAI,IAAI,OAAQ,WAAU,KAAK,YAAY,EAAE,QAAQ,IAAI,OAAO,CAAC,CAAC;AAClE,MAAI,IAAI,YAAa,WAAU,KAAK,MAAM,EAAE,OAAO,IAAI,YAAY,CAAC,CAAC;AACrE,SAAO;AACT;AAIA,IAAM,WAAW,MAAM;AACrB,MAAI,CAAC,QAAQ,KAAK,CAAC,EAAG,QAAO;AAC7B,MAAI;AACF,WAAO,aAAa,QAAQ,KAAK,CAAC,CAAC,MAAM,cAAc,YAAY,GAAG;AAAA,EACxE,QAAQ;AACN,WAAO;AAAA,EACT;AACF,GAAG;AAEH,IAAI,SAAS;AACX,QAAM,WAAW,aAAa,EAAE,WAAW,iBAAiB,EAAE,CAAC,CAAC;AAClE;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -1,61 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
var MODALITIES = ["image", "video", "audio", "text"];
|
|
6
|
-
var INTENTS = ["internal-moodboard", "commercial-product", "ai-generation-input", "redistribution"];
|
|
7
|
-
function toAgentRef(r) {
|
|
8
|
-
return {
|
|
9
|
-
id: r.id,
|
|
10
|
-
title: r.title,
|
|
11
|
-
modality: r.modality,
|
|
12
|
-
provider: r.source.providerId,
|
|
13
|
-
canonicalUrl: r.canonicalUrl,
|
|
14
|
-
license: r.rights.license,
|
|
15
|
-
thumbnail: r.thumbnail?.url,
|
|
16
|
-
excerpt: r.text?.excerpt
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
var agentRefSchema = z.object({
|
|
20
|
-
id: z.string(),
|
|
21
|
-
title: z.string().optional(),
|
|
22
|
-
modality: z.string(),
|
|
23
|
-
provider: z.string(),
|
|
24
|
-
canonicalUrl: z.string(),
|
|
25
|
-
license: z.string(),
|
|
26
|
-
thumbnail: z.string().optional(),
|
|
27
|
-
excerpt: z.string().optional()
|
|
28
|
-
});
|
|
29
|
-
function createRefkitMcpServer(refkit) {
|
|
30
|
-
const server = new McpServer({ name: "refkit", version: "0.0.0" });
|
|
31
|
-
server.registerTool(
|
|
32
|
-
"search_references",
|
|
33
|
-
{
|
|
34
|
-
title: "Search creative references",
|
|
35
|
-
description: "Search license-normalized reference material (images / text) across the configured clean sources. Every result carries a license id + canonical source link. Pass gateFor to return only results usable for a given intent (license-gated). Results are references, not rights clearance \u2014 not legal advice.",
|
|
36
|
-
inputSchema: {
|
|
37
|
-
query: z.string().describe('what to search for, e.g. "cyberpunk alley at night"'),
|
|
38
|
-
modalities: z.array(z.enum(MODALITIES)).optional().describe('default ["image"]'),
|
|
39
|
-
limit: z.number().int().positive().optional(),
|
|
40
|
-
gateFor: z.enum(INTENTS).optional().describe("only return results allowed for this intended use")
|
|
41
|
-
},
|
|
42
|
-
outputSchema: { references: z.array(agentRefSchema) }
|
|
43
|
-
},
|
|
44
|
-
async ({ query, modalities, limit, gateFor }) => {
|
|
45
|
-
const refs = await refkit.search({ query, modalities: modalities ?? ["image"], limit, gateFor });
|
|
46
|
-
const references = refs.map(toAgentRef);
|
|
47
|
-
return {
|
|
48
|
-
content: [{ type: "text", text: `${references.length} reference(s) for "${query}".` }],
|
|
49
|
-
structuredContent: { references }
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
);
|
|
53
|
-
return server;
|
|
54
|
-
}
|
|
55
|
-
async function serveStdio(refkit) {
|
|
56
|
-
const server = createRefkitMcpServer(refkit);
|
|
57
|
-
await server.connect(new StdioServerTransport());
|
|
58
|
-
}
|
|
1
|
+
import {
|
|
2
|
+
createRefkitMcpServer,
|
|
3
|
+
serveStdio
|
|
4
|
+
} from "./chunk-B5SVJVI4.js";
|
|
59
5
|
export {
|
|
60
6
|
createRefkitMcpServer,
|
|
61
7
|
serveStdio
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refkit/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.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",
|
|
@@ -15,6 +15,9 @@
|
|
|
15
15
|
],
|
|
16
16
|
"main": "./dist/index.js",
|
|
17
17
|
"types": "./dist/index.d.ts",
|
|
18
|
+
"bin": {
|
|
19
|
+
"refkit-mcp": "./dist/cli.js"
|
|
20
|
+
},
|
|
18
21
|
"exports": {
|
|
19
22
|
".": {
|
|
20
23
|
"types": "./dist/index.d.ts",
|
|
@@ -24,10 +27,19 @@
|
|
|
24
27
|
"dependencies": {
|
|
25
28
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
26
29
|
"zod": "^4.3.6",
|
|
27
|
-
"@refkit/core": "0.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"@refkit/provider-
|
|
30
|
+
"@refkit/core": "0.4.0",
|
|
31
|
+
"@refkit/provider-artic": "0.2.0",
|
|
32
|
+
"@refkit/provider-brave": "0.2.0",
|
|
33
|
+
"@refkit/provider-flickr": "0.2.0",
|
|
34
|
+
"@refkit/provider-gutendex": "0.2.0",
|
|
35
|
+
"@refkit/provider-met": "0.2.0",
|
|
36
|
+
"@refkit/provider-openverse": "0.2.0",
|
|
37
|
+
"@refkit/provider-pexels": "0.2.0",
|
|
38
|
+
"@refkit/provider-pixabay": "0.2.0",
|
|
39
|
+
"@refkit/provider-poetrydb": "0.2.0",
|
|
40
|
+
"@refkit/provider-smithsonian": "0.2.0",
|
|
41
|
+
"@refkit/provider-unsplash": "0.2.0",
|
|
42
|
+
"@refkit/provider-wikimedia-commons": "0.2.0"
|
|
31
43
|
},
|
|
32
44
|
"files": [
|
|
33
45
|
"dist",
|