@public-ui/mcp 4.0.0-alpha.2 → 4.0.0-alpha.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,46 +1,40 @@
1
1
  #!/usr/bin/env node
2
- import './index.mjs';
3
- import { createServer } from 'http';
4
- import { handleApiRequest } from './api-handler.mjs';
5
- import 'node:http';
6
- import './sample-index.mjs';
7
- import 'node:fs/promises';
8
- import 'node:path';
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { createRequire } from 'node:module';
4
+ import { getSampleIndexMetadata } from './data.mjs';
5
+ import { createKolibriMcpServer } from './mcp.mjs';
6
+ import 'node:fs';
9
7
  import 'node:url';
8
+ import '@modelcontextprotocol/sdk/server/mcp.js';
9
+ import '@modelcontextprotocol/sdk/server/streamableHttp.js';
10
+ import 'express';
11
+ import 'zod';
12
+ import './search.mjs';
13
+ import 'fuse.js';
10
14
 
11
- const PORT = process.env.PORT || 3030;
12
- const server = createServer((req, res) => {
13
- res.setHeader("Access-Control-Allow-Origin", "*");
14
- res.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
15
- res.setHeader("Access-Control-Allow-Headers", "Content-Type");
16
- if (req.method === "OPTIONS") {
17
- res.writeHead(200);
18
- res.end();
19
- return;
15
+ const require = createRequire(import.meta.url);
16
+ const { version: PACKAGE_VERSION = "0.0.0" } = require("../package.json");
17
+ const ENABLE_LOGGING = process.env.MCP_LOGGING === "true" || process.env.MCP_LOGGING === "1";
18
+ async function main() {
19
+ const server = createKolibriMcpServer();
20
+ const transport = new StdioServerTransport();
21
+ await server.connect(transport);
22
+ const metadata = getSampleIndexMetadata();
23
+ console.error(`
24
+ \u{1F680} KoliBri MCP Server v${PACKAGE_VERSION}`);
25
+ console.error("\u2501".repeat(50));
26
+ console.error(`\u{1F4CA} Loaded ${metadata.counts.total} entries:`);
27
+ console.error(` \u2022 ${metadata.counts.totalSamples} samples`);
28
+ console.error(` \u2022 ${metadata.counts.totalSpecs ?? 0} specs`);
29
+ console.error(` \u2022 ${metadata.counts.totalScenarios ?? 0} scenarios`);
30
+ console.error(` \u2022 ${metadata.counts.totalDocs} docs`);
31
+ console.error("\u2501".repeat(50));
32
+ if (ENABLE_LOGGING) {
33
+ console.error("\u{1F50D} Logging: ENABLED (MCP_LOGGING=true)");
34
+ } else {
35
+ console.error("\u{1F4A1} Logging: disabled (set MCP_LOGGING=true to enable)");
20
36
  }
21
- handleApiRequest(req);
22
- });
23
- server.listen(PORT, () => {
24
- console.log(`\u{1F680} KoliBri MCP Server running on http://localhost:${PORT}`);
25
- console.log(`\u{1F4CA} API endpoints:`);
26
- console.log(` GET /mcp/health - Server status`);
27
- console.log(` GET /mcp/samples - List all samples`);
28
- console.log(` GET /mcp/sample - Get specific sample`);
29
- console.log(` GET /mcp/docs - List docs`);
30
- console.log(` GET /mcp/doc - Get specific doc`);
31
- console.log(`\u{1F4DA} Documentation: https://www.npmjs.com/package/@public-ui/mcp`);
32
- });
33
- process.on("SIGTERM", () => {
34
- console.log("\u{1F6D1} Received SIGTERM, shutting down gracefully...");
35
- server.close(() => {
36
- console.log("\u2705 Server closed");
37
- process.exit(0);
38
- });
39
- });
40
- process.on("SIGINT", () => {
41
- console.log("\u{1F6D1} Received SIGINT, shutting down gracefully...");
42
- server.close(() => {
43
- console.log("\u2705 Server closed");
44
- process.exit(0);
45
- });
46
- });
37
+ console.error("\u{1F50C} Transport: stdio");
38
+ console.error("\u2705 Ready for MCP requests\n");
39
+ }
40
+ void main();
package/dist/data.cjs ADDED
@@ -0,0 +1,88 @@
1
+ 'use strict';
2
+
3
+ const node_fs = require('node:fs');
4
+ const node_url = require('node:url');
5
+
6
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
7
+ let cachedData;
8
+ function calculateCounts(entries) {
9
+ const byKind = {};
10
+ for (const entry of entries) {
11
+ const key = entry.kind;
12
+ byKind[key] = (byKind[key] ?? 0) + 1;
13
+ }
14
+ return {
15
+ total: entries.length,
16
+ totalDocs: byKind.doc ?? 0,
17
+ totalSamples: byKind.sample ?? 0,
18
+ totalScenarios: byKind.scenario ?? 0,
19
+ totalSpecs: byKind.spec ?? 0,
20
+ byKind
21
+ };
22
+ }
23
+ function normalizeEntry(entry) {
24
+ const normalizedKind = entry.kind === "doc" ? "doc" : entry.kind === "scenario" ? "scenario" : entry.kind === "spec" ? "spec" : "sample";
25
+ const tags = Array.isArray(entry.tags) ? entry.tags.map((tag) => String(tag)).filter((tag) => tag.trim().length > 0) : void 0;
26
+ return {
27
+ ...entry,
28
+ kind: normalizedKind,
29
+ tags
30
+ };
31
+ }
32
+ function normalizeMetadata(metadata, entries) {
33
+ const counts = calculateCounts(entries);
34
+ const repo = metadata?.repo ?? { commit: null, branch: null, repoUrl: null };
35
+ return {
36
+ generatedAt: metadata?.generatedAt ?? null,
37
+ buildMode: metadata?.buildMode ?? "unknown",
38
+ counts: {
39
+ total: metadata?.counts?.total ?? counts.total,
40
+ totalDocs: metadata?.counts?.totalDocs ?? counts.totalDocs,
41
+ totalSamples: metadata?.counts?.totalSamples ?? counts.totalSamples,
42
+ totalScenarios: metadata?.counts?.totalScenarios ?? counts.totalScenarios,
43
+ totalSpecs: metadata?.counts?.totalSpecs ?? counts.totalSpecs,
44
+ byKind: metadata?.counts?.byKind instanceof Map ? Object.fromEntries(metadata.counts.byKind.entries()) : metadata?.counts?.byKind ? Object.fromEntries(Object.entries(metadata.counts.byKind).map(([key, value]) => [key, Number(value)])) : counts.byKind
45
+ },
46
+ repo: {
47
+ commit: repo.commit ?? null,
48
+ branch: repo.branch ?? null,
49
+ repoUrl: repo.repoUrl ?? null
50
+ }
51
+ };
52
+ }
53
+ function loadSampleData() {
54
+ if (cachedData) {
55
+ return cachedData;
56
+ }
57
+ try {
58
+ const sharedIndexUrl = new URL("../shared/sample-index.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('data.cjs', document.baseURI).href)));
59
+ const filePath = node_url.fileURLToPath(sharedIndexUrl);
60
+ const raw = node_fs.readFileSync(filePath, "utf8");
61
+ const parsed = JSON.parse(raw);
62
+ const entries = Array.isArray(parsed.entries) ? parsed.entries.map(normalizeEntry) : [];
63
+ if (entries.length === 0) {
64
+ throw new Error("Sample index does not contain any entries.");
65
+ }
66
+ const metadata = normalizeMetadata(parsed.metadata, entries);
67
+ cachedData = { entries, metadata };
68
+ return cachedData;
69
+ } catch (error) {
70
+ const message = error instanceof Error ? error.message : String(error);
71
+ throw new Error(
72
+ `Failed to load sample index from shared/sample-index.json. Please run 'pnpm generate-index' to create the index file. Error: ${message}`
73
+ );
74
+ }
75
+ }
76
+ function getAllEntries() {
77
+ return loadSampleData().entries;
78
+ }
79
+ function getEntryById(id) {
80
+ return getAllEntries().find((entry) => entry.id === id);
81
+ }
82
+ function getSampleIndexMetadata() {
83
+ return loadSampleData().metadata;
84
+ }
85
+
86
+ exports.getAllEntries = getAllEntries;
87
+ exports.getEntryById = getEntryById;
88
+ exports.getSampleIndexMetadata = getSampleIndexMetadata;
@@ -0,0 +1,34 @@
1
+ interface SampleEntry {
2
+ id: string;
3
+ kind: 'doc' | 'sample' | 'scenario' | 'spec';
4
+ name: string;
5
+ group?: string;
6
+ description?: string;
7
+ tags?: string[];
8
+ code?: string;
9
+ path?: string;
10
+ }
11
+ interface SampleIndexCounts {
12
+ total: number;
13
+ totalDocs: number;
14
+ totalSamples: number;
15
+ totalScenarios: number;
16
+ totalSpecs: number;
17
+ byKind: Record<string, number>;
18
+ }
19
+ interface SampleIndexMetadata {
20
+ generatedAt: string | null;
21
+ buildMode: string;
22
+ counts: SampleIndexCounts;
23
+ repo: {
24
+ commit: string | null;
25
+ branch: string | null;
26
+ repoUrl: string | null;
27
+ };
28
+ }
29
+ declare function getAllEntries(): SampleEntry[];
30
+ declare function getEntryById(id: string): SampleEntry | undefined;
31
+ declare function getSampleIndexMetadata(): SampleIndexMetadata;
32
+
33
+ export { getAllEntries, getEntryById, getSampleIndexMetadata };
34
+ export type { SampleEntry };
@@ -0,0 +1,34 @@
1
+ interface SampleEntry {
2
+ id: string;
3
+ kind: 'doc' | 'sample' | 'scenario' | 'spec';
4
+ name: string;
5
+ group?: string;
6
+ description?: string;
7
+ tags?: string[];
8
+ code?: string;
9
+ path?: string;
10
+ }
11
+ interface SampleIndexCounts {
12
+ total: number;
13
+ totalDocs: number;
14
+ totalSamples: number;
15
+ totalScenarios: number;
16
+ totalSpecs: number;
17
+ byKind: Record<string, number>;
18
+ }
19
+ interface SampleIndexMetadata {
20
+ generatedAt: string | null;
21
+ buildMode: string;
22
+ counts: SampleIndexCounts;
23
+ repo: {
24
+ commit: string | null;
25
+ branch: string | null;
26
+ repoUrl: string | null;
27
+ };
28
+ }
29
+ declare function getAllEntries(): SampleEntry[];
30
+ declare function getEntryById(id: string): SampleEntry | undefined;
31
+ declare function getSampleIndexMetadata(): SampleIndexMetadata;
32
+
33
+ export { getAllEntries, getEntryById, getSampleIndexMetadata };
34
+ export type { SampleEntry };
package/dist/data.d.ts ADDED
@@ -0,0 +1,34 @@
1
+ interface SampleEntry {
2
+ id: string;
3
+ kind: 'doc' | 'sample' | 'scenario' | 'spec';
4
+ name: string;
5
+ group?: string;
6
+ description?: string;
7
+ tags?: string[];
8
+ code?: string;
9
+ path?: string;
10
+ }
11
+ interface SampleIndexCounts {
12
+ total: number;
13
+ totalDocs: number;
14
+ totalSamples: number;
15
+ totalScenarios: number;
16
+ totalSpecs: number;
17
+ byKind: Record<string, number>;
18
+ }
19
+ interface SampleIndexMetadata {
20
+ generatedAt: string | null;
21
+ buildMode: string;
22
+ counts: SampleIndexCounts;
23
+ repo: {
24
+ commit: string | null;
25
+ branch: string | null;
26
+ repoUrl: string | null;
27
+ };
28
+ }
29
+ declare function getAllEntries(): SampleEntry[];
30
+ declare function getEntryById(id: string): SampleEntry | undefined;
31
+ declare function getSampleIndexMetadata(): SampleIndexMetadata;
32
+
33
+ export { getAllEntries, getEntryById, getSampleIndexMetadata };
34
+ export type { SampleEntry };
package/dist/data.mjs ADDED
@@ -0,0 +1,83 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { fileURLToPath } from 'node:url';
3
+
4
+ let cachedData;
5
+ function calculateCounts(entries) {
6
+ const byKind = {};
7
+ for (const entry of entries) {
8
+ const key = entry.kind;
9
+ byKind[key] = (byKind[key] ?? 0) + 1;
10
+ }
11
+ return {
12
+ total: entries.length,
13
+ totalDocs: byKind.doc ?? 0,
14
+ totalSamples: byKind.sample ?? 0,
15
+ totalScenarios: byKind.scenario ?? 0,
16
+ totalSpecs: byKind.spec ?? 0,
17
+ byKind
18
+ };
19
+ }
20
+ function normalizeEntry(entry) {
21
+ const normalizedKind = entry.kind === "doc" ? "doc" : entry.kind === "scenario" ? "scenario" : entry.kind === "spec" ? "spec" : "sample";
22
+ const tags = Array.isArray(entry.tags) ? entry.tags.map((tag) => String(tag)).filter((tag) => tag.trim().length > 0) : void 0;
23
+ return {
24
+ ...entry,
25
+ kind: normalizedKind,
26
+ tags
27
+ };
28
+ }
29
+ function normalizeMetadata(metadata, entries) {
30
+ const counts = calculateCounts(entries);
31
+ const repo = metadata?.repo ?? { commit: null, branch: null, repoUrl: null };
32
+ return {
33
+ generatedAt: metadata?.generatedAt ?? null,
34
+ buildMode: metadata?.buildMode ?? "unknown",
35
+ counts: {
36
+ total: metadata?.counts?.total ?? counts.total,
37
+ totalDocs: metadata?.counts?.totalDocs ?? counts.totalDocs,
38
+ totalSamples: metadata?.counts?.totalSamples ?? counts.totalSamples,
39
+ totalScenarios: metadata?.counts?.totalScenarios ?? counts.totalScenarios,
40
+ totalSpecs: metadata?.counts?.totalSpecs ?? counts.totalSpecs,
41
+ byKind: metadata?.counts?.byKind instanceof Map ? Object.fromEntries(metadata.counts.byKind.entries()) : metadata?.counts?.byKind ? Object.fromEntries(Object.entries(metadata.counts.byKind).map(([key, value]) => [key, Number(value)])) : counts.byKind
42
+ },
43
+ repo: {
44
+ commit: repo.commit ?? null,
45
+ branch: repo.branch ?? null,
46
+ repoUrl: repo.repoUrl ?? null
47
+ }
48
+ };
49
+ }
50
+ function loadSampleData() {
51
+ if (cachedData) {
52
+ return cachedData;
53
+ }
54
+ try {
55
+ const sharedIndexUrl = new URL("../shared/sample-index.json", import.meta.url);
56
+ const filePath = fileURLToPath(sharedIndexUrl);
57
+ const raw = readFileSync(filePath, "utf8");
58
+ const parsed = JSON.parse(raw);
59
+ const entries = Array.isArray(parsed.entries) ? parsed.entries.map(normalizeEntry) : [];
60
+ if (entries.length === 0) {
61
+ throw new Error("Sample index does not contain any entries.");
62
+ }
63
+ const metadata = normalizeMetadata(parsed.metadata, entries);
64
+ cachedData = { entries, metadata };
65
+ return cachedData;
66
+ } catch (error) {
67
+ const message = error instanceof Error ? error.message : String(error);
68
+ throw new Error(
69
+ `Failed to load sample index from shared/sample-index.json. Please run 'pnpm generate-index' to create the index file. Error: ${message}`
70
+ );
71
+ }
72
+ }
73
+ function getAllEntries() {
74
+ return loadSampleData().entries;
75
+ }
76
+ function getEntryById(id) {
77
+ return getAllEntries().find((entry) => entry.id === id);
78
+ }
79
+ function getSampleIndexMetadata() {
80
+ return loadSampleData().metadata;
81
+ }
82
+
83
+ export { getAllEntries, getEntryById, getSampleIndexMetadata };
package/dist/mcp.cjs ADDED
@@ -0,0 +1,298 @@
1
+ 'use strict';
2
+
3
+ const mcp_js = require('@modelcontextprotocol/sdk/server/mcp.js');
4
+ const streamableHttp_js = require('@modelcontextprotocol/sdk/server/streamableHttp.js');
5
+ const express = require('express');
6
+ const node_module = require('node:module');
7
+ const zod = require('zod');
8
+ const data = require('./data.cjs');
9
+ const search = require('./search.cjs');
10
+ require('node:fs');
11
+ require('node:url');
12
+ require('fuse.js');
13
+
14
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
15
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
16
+
17
+ const express__default = /*#__PURE__*/_interopDefaultCompat(express);
18
+
19
+ const KIND_OPTIONS = ["doc", "sample", "scenario", "spec"];
20
+ function isValidKind(value) {
21
+ return typeof value === "string" && KIND_OPTIONS.includes(value);
22
+ }
23
+ function normalizeTags(tags) {
24
+ return Array.isArray(tags) ? tags : [];
25
+ }
26
+ function formatTagsForText(tags) {
27
+ const normalized = normalizeTags(tags);
28
+ return normalized.length > 0 ? normalized.join(", ") : "none";
29
+ }
30
+ const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('mcp.cjs', document.baseURI).href)));
31
+ const {
32
+ version: PACKAGE_VERSION = "0.0.0",
33
+ name: PACKAGE_NAME = "@public-ui/mcp",
34
+ description: PACKAGE_DESCRIPTION
35
+ } = require$1("../package.json");
36
+ const ENABLE_LOGGING = process.env.MCP_LOGGING === "true" || process.env.MCP_LOGGING === "1";
37
+ function log(type, message, data) {
38
+ if (!ENABLE_LOGGING) return;
39
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
40
+ const prefix = `[${timestamp}] [${type.toUpperCase()}]`;
41
+ if (data) {
42
+ console.error(`${prefix} ${message}`, JSON.stringify(data, null, 2));
43
+ } else {
44
+ console.error(`${prefix} ${message}`);
45
+ }
46
+ }
47
+ function createKolibriMcpServer() {
48
+ const server = new mcp_js.McpServer({
49
+ name: PACKAGE_NAME,
50
+ version: PACKAGE_VERSION
51
+ });
52
+ return configureServer(server);
53
+ }
54
+ function configureServer(server) {
55
+ server.registerTool(
56
+ "search",
57
+ {
58
+ title: "Search KoliBri Samples and Docs",
59
+ description: 'Search for KoliBri component samples, scenarios, specifications, and documentation using fuzzy search. Parameters: query (optional string), kind (optional select: "doc", "sample", "scenario", or "spec"), limit (optional number, default 10).',
60
+ inputSchema: {
61
+ query: zod.z.string().optional().default(""),
62
+ kind: zod.z.enum(KIND_OPTIONS).optional(),
63
+ limit: zod.z.number().optional()
64
+ },
65
+ outputSchema: {
66
+ query: zod.z.string(),
67
+ totalResults: zod.z.number()
68
+ }
69
+ },
70
+ ({ query, kind, limit }) => {
71
+ log("tool", "search called", { query, kind, limit });
72
+ const queryStr = typeof query === "string" ? query : "";
73
+ const allEntries = data.getAllEntries();
74
+ const searchOptions = {
75
+ limit: typeof limit === "number" ? limit : 10
76
+ };
77
+ if (isValidKind(kind)) {
78
+ searchOptions.kind = kind;
79
+ }
80
+ const results = search.searchEntries(allEntries, queryStr, searchOptions);
81
+ log("tool", "search completed", {
82
+ query: queryStr,
83
+ resultCount: results.length,
84
+ options: searchOptions
85
+ });
86
+ const structuredContent = {
87
+ query: queryStr,
88
+ totalResults: results.length,
89
+ results: results.map(({ item, score }) => ({
90
+ id: item.id,
91
+ kind: item.kind,
92
+ name: item.name,
93
+ group: item.group ?? "N/A",
94
+ description: item.description ?? "N/A",
95
+ tags: normalizeTags(item.tags),
96
+ score: score ?? 1,
97
+ path: item.path ?? "N/A"
98
+ }))
99
+ };
100
+ const resultText = results.length ? results.map(({ item, score }, index) => {
101
+ const matchScore = ((score ?? 1) * 100).toFixed(1);
102
+ const pathLine = item.path ? `
103
+ Path: ${item.path}` : "";
104
+ return `${index + 1}. [${item.kind}] ${item.id}: ${item.name}
105
+ Description: ${item.description ?? "N/A"}
106
+ Match score: ${matchScore}%
107
+ Tags: ${formatTagsForText(item.tags)}${pathLine}`;
108
+ }).join("\n\n") : "No matches found.";
109
+ const tipText = results.length ? "\n\n\u{1F4A1} Tip: Use 'fetch' with any ID above to see full entry details." : "";
110
+ return {
111
+ content: [
112
+ {
113
+ type: "text",
114
+ text: `Found ${results.length} result(s) for "${queryStr}":
115
+
116
+ ${resultText}${tipText}`
117
+ }
118
+ ],
119
+ structuredContent
120
+ };
121
+ }
122
+ );
123
+ server.registerTool(
124
+ "fetch",
125
+ {
126
+ title: "Get Sample or Doc Entry",
127
+ description: 'Get a specific sample, specification, or documentation entry by its ID. Parameter: id (required string, e.g. "button/basic", "spec/button", or "docs/getting-started")',
128
+ inputSchema: {
129
+ id: zod.z.string()
130
+ },
131
+ outputSchema: {
132
+ id: zod.z.string(),
133
+ kind: zod.z.string(),
134
+ name: zod.z.string()
135
+ }
136
+ },
137
+ ({ id }) => {
138
+ log("tool", "fetch called", { id });
139
+ const idStr = String(id ?? "");
140
+ if (!idStr) {
141
+ log("error", "fetch failed: empty id");
142
+ throw new Error("ID parameter is required");
143
+ }
144
+ const entry = data.getEntryById(idStr);
145
+ if (!entry) {
146
+ log("error", "fetch failed: entry not found", { id: idStr });
147
+ throw new Error(`Entry with ID "${idStr}" not found`);
148
+ }
149
+ log("tool", "fetch completed", { id: idStr, kind: entry.kind });
150
+ const output = {
151
+ id: entry.id,
152
+ kind: entry.kind,
153
+ name: entry.name,
154
+ group: entry.group ?? "N/A",
155
+ description: entry.description ?? "N/A",
156
+ tags: entry.tags ?? [],
157
+ code: entry.code ?? "No code available",
158
+ path: entry.path ?? "N/A"
159
+ };
160
+ return {
161
+ content: [
162
+ {
163
+ type: "text",
164
+ text: `# ${entry.name}
165
+
166
+ ID: ${entry.id}
167
+ Kind: ${entry.kind}
168
+ Group: ${entry.group ?? "N/A"}
169
+ Description: ${entry.description ?? "N/A"}
170
+ Tags: ${entry.tags?.join(", ") ?? "none"}
171
+
172
+ ## Code
173
+
174
+ \`\`\`
175
+ ${entry.code ?? "No code available"}
176
+ \`\`\``
177
+ }
178
+ ],
179
+ structuredContent: output
180
+ };
181
+ }
182
+ );
183
+ server.registerResource(
184
+ "info",
185
+ new mcp_js.ResourceTemplate("kolibri://info", { list: void 0 }),
186
+ {
187
+ title: "KoliBri MCP Server Info",
188
+ description: "Get information about the KoliBri MCP Server and available samples"
189
+ },
190
+ (uri) => {
191
+ log("resource", "info accessed", { uri: uri.href });
192
+ const metadata = data.getSampleIndexMetadata();
193
+ const infoText = `# KoliBri MCP Server v${PACKAGE_VERSION}
194
+
195
+ ${PACKAGE_DESCRIPTION ?? ""}
196
+
197
+ ## Sample Index
198
+ - Generated: ${metadata.generatedAt ?? "unknown"}
199
+ - Build mode: ${metadata.buildMode}
200
+ - Total entries: ${metadata.counts.total}
201
+ - Documentation: ${metadata.counts.totalDocs}
202
+ - Specifications: ${metadata.counts.totalSpecs ?? 0}
203
+ - Samples: ${metadata.counts.totalSamples}
204
+ - Scenarios: ${metadata.counts.totalScenarios ?? 0}
205
+
206
+ ## Repository
207
+ - Branch: ${metadata.repo.branch ?? "N/A"}
208
+ - Commit: ${metadata.repo.commit ?? "N/A"}
209
+ - URL: ${metadata.repo.repoUrl ?? "N/A"}
210
+ `;
211
+ return {
212
+ contents: [
213
+ {
214
+ uri: uri.href,
215
+ mimeType: "text/markdown",
216
+ text: infoText
217
+ }
218
+ ]
219
+ };
220
+ }
221
+ );
222
+ server.registerResource(
223
+ "best-practices",
224
+ new mcp_js.ResourceTemplate("kolibri://best-practices", { list: void 0 }),
225
+ {
226
+ title: "KoliBri Best Practices",
227
+ description: "Essential guidelines for working with KoliBri Web Components"
228
+ },
229
+ (uri) => {
230
+ log("resource", "best-practices accessed", { uri: uri.href });
231
+ const practicesText = `# KoliBri Web Components - Best Practices
232
+
233
+ ## Essential Guidelines
234
+
235
+ 1. **Component Registration**
236
+ Always register KoliBri Web Components in the browser runtime before rendering them.
237
+
238
+ 2. **Integration Setup**
239
+ Choose the integration guide that matches your project setup to load and bundle the components correctly.
240
+
241
+ 3. **Icon Font Assets**
242
+ Bundle the KoliBri icon font assets (for example codicon.css and codicon.ttf) so kol-icon glyphs can render.
243
+
244
+ 4. **Form Validation**
245
+ Wrap input elements with <kol-form> and feed its _errorList to surface validation issues via the generated error summary.
246
+
247
+ ## Additional Resources
248
+
249
+ Use the 'search' tool to find specific component examples and implementation details.
250
+ Use the 'fetch' tool to retrieve full code samples for specific components.
251
+ `;
252
+ return {
253
+ contents: [
254
+ {
255
+ uri: uri.href,
256
+ mimeType: "text/markdown",
257
+ text: practicesText
258
+ }
259
+ ]
260
+ };
261
+ }
262
+ );
263
+ return server;
264
+ }
265
+ if ((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('mcp.cjs', document.baseURI).href)) === `file://${process.argv[1]}` || process.argv[1]?.endsWith("/mcp.ts") || process.argv[1]?.endsWith("/mcp.cjs") || process.argv[1]?.endsWith("/mcp.mjs")) {
266
+ const server = createKolibriMcpServer();
267
+ const app = express__default();
268
+ app.use(express__default.json());
269
+ app.post("/mcp", async (req, res) => {
270
+ const transport = new streamableHttp_js.StreamableHTTPServerTransport({
271
+ sessionIdGenerator: void 0,
272
+ enableJsonResponse: true
273
+ });
274
+ res.on("close", () => {
275
+ void transport.close();
276
+ });
277
+ await server.connect(transport);
278
+ await transport.handleRequest(req, res, req.body);
279
+ });
280
+ const port = parseInt(process.env.PORT || "3000");
281
+ void app.listen(port, () => {
282
+ console.log(`KoliBri MCP Server v${PACKAGE_VERSION} running on http://localhost:${port}/mcp`);
283
+ const metadata = data.getSampleIndexMetadata();
284
+ console.log(
285
+ `Loaded ${metadata.counts.total} entries (${metadata.counts.totalDocs} docs, ${metadata.counts.totalSamples} samples, ${metadata.counts.totalScenarios ?? 0} scenarios)`
286
+ );
287
+ if (ENABLE_LOGGING) {
288
+ console.log("\u{1F50D} Logging is ENABLED (MCP_LOGGING=true)");
289
+ } else {
290
+ console.log("\u{1F4A1} Logging is disabled. Set MCP_LOGGING=true to enable request logging");
291
+ }
292
+ }).on("error", (error) => {
293
+ console.error("Server error:", error);
294
+ process.exit(1);
295
+ });
296
+ }
297
+
298
+ exports.createKolibriMcpServer = createKolibriMcpServer;
package/dist/mcp.d.cts ADDED
@@ -0,0 +1,9 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ /**
4
+ * Create a configured KoliBri MCP server instance.
5
+ * Can be used with both stdio and HTTP transports.
6
+ */
7
+ declare function createKolibriMcpServer(): McpServer;
8
+
9
+ export { createKolibriMcpServer };
package/dist/mcp.d.mts ADDED
@@ -0,0 +1,9 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ /**
4
+ * Create a configured KoliBri MCP server instance.
5
+ * Can be used with both stdio and HTTP transports.
6
+ */
7
+ declare function createKolibriMcpServer(): McpServer;
8
+
9
+ export { createKolibriMcpServer };
package/dist/mcp.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+
3
+ /**
4
+ * Create a configured KoliBri MCP server instance.
5
+ * Can be used with both stdio and HTTP transports.
6
+ */
7
+ declare function createKolibriMcpServer(): McpServer;
8
+
9
+ export { createKolibriMcpServer };