@public-ui/mcp 4.3.0-rc.8 → 4.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/dist/cli.cjs +1 -3
- package/dist/cli.mjs +1 -3
- package/dist/mcp.cjs +21 -168
- package/dist/mcp.d.cts +1 -1
- package/dist/mcp.d.mts +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.mjs +23 -169
- package/package.json +8 -8
- package/shared/sample-index.json +2 -2
- package/shared/template-index.json +1799 -0
package/dist/cli.cjs
CHANGED
|
@@ -14,15 +14,13 @@ require('zod');
|
|
|
14
14
|
require('./search.cjs');
|
|
15
15
|
require('fuse.js');
|
|
16
16
|
require('node:path');
|
|
17
|
-
require('glob');
|
|
18
|
-
require('simple-git');
|
|
19
17
|
|
|
20
18
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
21
19
|
const require$1 = node_module.createRequire((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('cli.cjs', document.baseURI).href)));
|
|
22
20
|
const { version: PACKAGE_VERSION = "0.0.0" } = require$1("../package.json");
|
|
23
21
|
const ENABLE_LOGGING = process.env.MCP_LOGGING === "true" || process.env.MCP_LOGGING === "1";
|
|
24
22
|
async function main() {
|
|
25
|
-
const server =
|
|
23
|
+
const server = mcp.createKolibriMcpServer();
|
|
26
24
|
const transport = new stdio_js.StdioServerTransport();
|
|
27
25
|
await server.connect(transport);
|
|
28
26
|
const metadata = data.getSampleIndexMetadata();
|
package/dist/cli.mjs
CHANGED
|
@@ -12,14 +12,12 @@ import 'zod';
|
|
|
12
12
|
import './search.mjs';
|
|
13
13
|
import 'fuse.js';
|
|
14
14
|
import 'node:path';
|
|
15
|
-
import 'glob';
|
|
16
|
-
import 'simple-git';
|
|
17
15
|
|
|
18
16
|
const require$1 = createRequire(import.meta.url);
|
|
19
17
|
const { version: PACKAGE_VERSION = "0.0.0" } = require$1("../package.json");
|
|
20
18
|
const ENABLE_LOGGING = process.env.MCP_LOGGING === "true" || process.env.MCP_LOGGING === "1";
|
|
21
19
|
async function main() {
|
|
22
|
-
const server =
|
|
20
|
+
const server = createKolibriMcpServer();
|
|
23
21
|
const transport = new StdioServerTransport();
|
|
24
22
|
await server.connect(transport);
|
|
25
23
|
const metadata = getSampleIndexMetadata();
|
package/dist/mcp.cjs
CHANGED
|
@@ -9,16 +9,13 @@ const data = require('./data.cjs');
|
|
|
9
9
|
const search = require('./search.cjs');
|
|
10
10
|
const node_fs = require('node:fs');
|
|
11
11
|
const node_path = require('node:path');
|
|
12
|
-
const
|
|
13
|
-
const simpleGit = require('simple-git');
|
|
14
|
-
require('node:url');
|
|
12
|
+
const node_url = require('node:url');
|
|
15
13
|
require('fuse.js');
|
|
16
14
|
|
|
17
15
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
18
16
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
19
17
|
|
|
20
18
|
const express__default = /*#__PURE__*/_interopDefaultCompat(express);
|
|
21
|
-
const simpleGit__default = /*#__PURE__*/_interopDefaultCompat(simpleGit);
|
|
22
19
|
|
|
23
20
|
const TEMPLATE_REPOS = [
|
|
24
21
|
{
|
|
@@ -59,151 +56,6 @@ const TEMPLATE_REPOS = [
|
|
|
59
56
|
}
|
|
60
57
|
];
|
|
61
58
|
|
|
62
|
-
const CACHE_DIR$1 = node_path.join(process.cwd(), "data", "templates");
|
|
63
|
-
async function cloneOrUpdateRepo(repoConfig) {
|
|
64
|
-
const repoPath = node_path.join(CACHE_DIR$1, repoConfig.id);
|
|
65
|
-
const git = simpleGit__default();
|
|
66
|
-
try {
|
|
67
|
-
const exists = await node_fs.promises.access(repoPath).then(() => true).catch(() => false);
|
|
68
|
-
if (exists) {
|
|
69
|
-
await git.cwd(repoPath).pull();
|
|
70
|
-
console.log(`\u2705 Updated ${repoConfig.id}`);
|
|
71
|
-
} else {
|
|
72
|
-
await git.clone(`https://github.com/${repoConfig.owner}/${repoConfig.repo}.git`, repoPath, [
|
|
73
|
-
"--branch",
|
|
74
|
-
repoConfig.branch,
|
|
75
|
-
"--single-branch",
|
|
76
|
-
"--depth",
|
|
77
|
-
"1"
|
|
78
|
-
]);
|
|
79
|
-
console.log(`\u2705 Cloned ${repoConfig.id}`);
|
|
80
|
-
}
|
|
81
|
-
return repoPath;
|
|
82
|
-
} catch (error) {
|
|
83
|
-
console.error(`\u274C Error cloning/updating ${repoConfig.id}:`, error);
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
async function findFilesInRepo(repoPath, repoConfig) {
|
|
88
|
-
const allFiles = [];
|
|
89
|
-
for (const pattern of repoConfig.includePatterns) {
|
|
90
|
-
const files = await glob.glob(pattern, {
|
|
91
|
-
cwd: repoPath,
|
|
92
|
-
ignore: repoConfig.excludePatterns,
|
|
93
|
-
nodir: true
|
|
94
|
-
});
|
|
95
|
-
allFiles.push(...files);
|
|
96
|
-
}
|
|
97
|
-
return [...new Set(allFiles)];
|
|
98
|
-
}
|
|
99
|
-
function getResourceType(filePath) {
|
|
100
|
-
if (filePath.endsWith(".md") || filePath.endsWith(".markdown")) {
|
|
101
|
-
return "markdown";
|
|
102
|
-
}
|
|
103
|
-
if (filePath.endsWith(".json") || filePath.endsWith(".yaml") || filePath.endsWith(".yml")) {
|
|
104
|
-
return "config";
|
|
105
|
-
}
|
|
106
|
-
return "code";
|
|
107
|
-
}
|
|
108
|
-
function getLanguage(filePath) {
|
|
109
|
-
const extension = filePath.split(".").pop()?.toLowerCase();
|
|
110
|
-
const languageMap = {
|
|
111
|
-
ts: "typescript",
|
|
112
|
-
tsx: "typescript",
|
|
113
|
-
js: "javascript",
|
|
114
|
-
jsx: "javascript",
|
|
115
|
-
css: "css",
|
|
116
|
-
scss: "scss",
|
|
117
|
-
html: "html",
|
|
118
|
-
json: "json",
|
|
119
|
-
yaml: "yaml",
|
|
120
|
-
yml: "yaml"
|
|
121
|
-
};
|
|
122
|
-
return languageMap[extension || ""] || extension || "unknown";
|
|
123
|
-
}
|
|
124
|
-
function extractFrontmatter(content) {
|
|
125
|
-
const frontmatterRegex = /^---[\s\S]*?---/;
|
|
126
|
-
const match = content.match(frontmatterRegex);
|
|
127
|
-
if (!match) return {};
|
|
128
|
-
try {
|
|
129
|
-
const frontmatter = match[0].replace(/^---|---$/g, "").trim();
|
|
130
|
-
const metadata = {};
|
|
131
|
-
frontmatter.split("\n").forEach((line) => {
|
|
132
|
-
const [key, value] = line.split(":").map((s) => s.trim());
|
|
133
|
-
if (key && value) {
|
|
134
|
-
metadata[key] = value.replace(/^['"]|['"]$/g, "");
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
return metadata;
|
|
138
|
-
} catch {
|
|
139
|
-
return {};
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
async function indexFile(repoPath, filePath, repoConfig) {
|
|
143
|
-
const absolutePath = node_path.join(repoPath, filePath);
|
|
144
|
-
const content = await node_fs.promises.readFile(absolutePath, "utf-8");
|
|
145
|
-
const stats = await node_fs.promises.stat(absolutePath);
|
|
146
|
-
const resourceType = getResourceType(filePath);
|
|
147
|
-
const frontmatter = resourceType === "markdown" ? extractFrontmatter(content) : {};
|
|
148
|
-
const lines = content.split("\n").length;
|
|
149
|
-
return {
|
|
150
|
-
id: `${repoConfig.id}:${filePath.replace(/[/\\]/g, ":")}`,
|
|
151
|
-
repoId: repoConfig.id,
|
|
152
|
-
path: filePath,
|
|
153
|
-
type: resourceType,
|
|
154
|
-
content,
|
|
155
|
-
metadata: {
|
|
156
|
-
name: frontmatter.title || filePath.split("/").pop() || "",
|
|
157
|
-
description: frontmatter.description || void 0,
|
|
158
|
-
tags: [...repoConfig.tags || [], ...frontmatter.tags ?? []].filter((t) => t),
|
|
159
|
-
templateType: repoConfig.type,
|
|
160
|
-
language: resourceType === "code" ? getLanguage(filePath) : void 0
|
|
161
|
-
},
|
|
162
|
-
stats: {
|
|
163
|
-
size: stats.size,
|
|
164
|
-
lines,
|
|
165
|
-
lastModified: stats.mtime.toISOString()
|
|
166
|
-
}
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
async function indexTemplateRepo(repoConfig) {
|
|
170
|
-
console.log(`\u{1F4C1} Indexing ${repoConfig.id}...`);
|
|
171
|
-
const repoPath = await cloneOrUpdateRepo(repoConfig);
|
|
172
|
-
const files = await findFilesInRepo(repoPath, repoConfig);
|
|
173
|
-
console.log(` Found ${files.length} files to index`);
|
|
174
|
-
const resources = [];
|
|
175
|
-
for (const file of files) {
|
|
176
|
-
try {
|
|
177
|
-
const resource = await indexFile(repoPath, file, repoConfig);
|
|
178
|
-
resources.push(resource);
|
|
179
|
-
} catch (error) {
|
|
180
|
-
console.warn(` \u26A0\uFE0F Could not index ${file}:`, error);
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
console.log(`\u2705 Indexed ${resources.length} resources from ${repoConfig.id}`);
|
|
184
|
-
return resources;
|
|
185
|
-
}
|
|
186
|
-
async function indexAllTemplateRepos() {
|
|
187
|
-
const allResources = [];
|
|
188
|
-
for (const repoConfig of TEMPLATE_REPOS) {
|
|
189
|
-
try {
|
|
190
|
-
const resources = await indexTemplateRepo(repoConfig);
|
|
191
|
-
allResources.push(...resources);
|
|
192
|
-
} catch (error) {
|
|
193
|
-
console.error(`\u274C Failed to index ${repoConfig.id}:`, error);
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
return allResources;
|
|
197
|
-
}
|
|
198
|
-
async function updateTemplateIndex() {
|
|
199
|
-
console.log("\u{1F504} Updating template index...");
|
|
200
|
-
const resources = await indexAllTemplateRepos();
|
|
201
|
-
const indexPath = node_path.join(CACHE_DIR$1, "template-index.json");
|
|
202
|
-
await node_fs.promises.mkdir(CACHE_DIR$1, { recursive: true });
|
|
203
|
-
await node_fs.promises.writeFile(indexPath, JSON.stringify(resources, null, 2));
|
|
204
|
-
console.log(`\u2705 Template index updated with ${resources.length} resources`);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
59
|
function extractCodeBlocksFromMarkdown(markdown) {
|
|
208
60
|
const codeBlockRegex = /```(\w*)\s*([\s\S]*?)```/g;
|
|
209
61
|
const blocks = [];
|
|
@@ -240,30 +92,31 @@ function calculateSimilarityScore(resource, query) {
|
|
|
240
92
|
return score;
|
|
241
93
|
}
|
|
242
94
|
|
|
243
|
-
|
|
95
|
+
function getIndexPath() {
|
|
96
|
+
const currentDir = node_url.fileURLToPath(new URL(".", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('mcp.cjs', document.baseURI).href))));
|
|
97
|
+
if (currentDir.includes("/dist/")) {
|
|
98
|
+
return node_path.resolve(currentDir, "../shared/template-index.json");
|
|
99
|
+
}
|
|
100
|
+
return node_path.resolve(currentDir, "../../shared/template-index.json");
|
|
101
|
+
}
|
|
102
|
+
const INDEX_PATH = getIndexPath();
|
|
244
103
|
let templateIndex = [];
|
|
245
|
-
|
|
104
|
+
function loadTemplateIndex() {
|
|
246
105
|
try {
|
|
247
|
-
const
|
|
248
|
-
const content = await node_fs.promises.readFile(indexPath, "utf-8");
|
|
106
|
+
const content = node_fs.readFileSync(INDEX_PATH, "utf-8");
|
|
249
107
|
const parsed = JSON.parse(content);
|
|
250
108
|
return Array.isArray(parsed) ? parsed : [];
|
|
251
109
|
} catch {
|
|
252
110
|
return [];
|
|
253
111
|
}
|
|
254
112
|
}
|
|
255
|
-
|
|
113
|
+
function initializeTemplateIndex() {
|
|
256
114
|
console.log("\u{1F4DA} Initializing template index...");
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
templateIndex = await loadTemplateIndex();
|
|
262
|
-
}
|
|
115
|
+
templateIndex = loadTemplateIndex();
|
|
116
|
+
if (templateIndex.length === 0) {
|
|
117
|
+
console.warn("\u26A0\uFE0F Template index is empty. Run `pnpm update-templates` before building to include template data.");
|
|
118
|
+
} else {
|
|
263
119
|
console.log(`\u2705 Template index loaded with ${templateIndex.length} resources`);
|
|
264
|
-
} catch (error) {
|
|
265
|
-
console.error("\u274C Failed to initialize template index:", error);
|
|
266
|
-
templateIndex = [];
|
|
267
120
|
}
|
|
268
121
|
}
|
|
269
122
|
function searchTemplates(query, options = {}) {
|
|
@@ -339,16 +192,16 @@ function log(type, message, data) {
|
|
|
339
192
|
console.error(`${prefix} ${message}`);
|
|
340
193
|
}
|
|
341
194
|
}
|
|
342
|
-
|
|
195
|
+
function createKolibriMcpServer() {
|
|
343
196
|
const server = new mcp_js.McpServer({
|
|
344
197
|
name: PACKAGE_NAME,
|
|
345
198
|
version: PACKAGE_VERSION
|
|
346
199
|
});
|
|
347
200
|
return configureServer(server);
|
|
348
201
|
}
|
|
349
|
-
|
|
202
|
+
function configureServer(server) {
|
|
350
203
|
try {
|
|
351
|
-
|
|
204
|
+
initializeTemplateIndex();
|
|
352
205
|
} catch (error) {
|
|
353
206
|
console.error("Failed to initialize template index:", error);
|
|
354
207
|
}
|
|
@@ -745,8 +598,8 @@ Use the 'fetch' tool to retrieve full code samples for specific components.
|
|
|
745
598
|
return server;
|
|
746
599
|
}
|
|
747
600
|
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")) {
|
|
748
|
-
void (
|
|
749
|
-
const server =
|
|
601
|
+
void (() => {
|
|
602
|
+
const server = createKolibriMcpServer();
|
|
750
603
|
const app = express__default();
|
|
751
604
|
app.use(express__default.json());
|
|
752
605
|
app.post("/mcp", async (req, res) => {
|
package/dist/mcp.d.cts
CHANGED
|
@@ -4,6 +4,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
4
4
|
* Create a configured KoliBri MCP server instance.
|
|
5
5
|
* Can be used with both stdio and HTTP transports.
|
|
6
6
|
*/
|
|
7
|
-
declare function createKolibriMcpServer():
|
|
7
|
+
declare function createKolibriMcpServer(): McpServer;
|
|
8
8
|
|
|
9
9
|
export { createKolibriMcpServer };
|
package/dist/mcp.d.mts
CHANGED
|
@@ -4,6 +4,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
4
4
|
* Create a configured KoliBri MCP server instance.
|
|
5
5
|
* Can be used with both stdio and HTTP transports.
|
|
6
6
|
*/
|
|
7
|
-
declare function createKolibriMcpServer():
|
|
7
|
+
declare function createKolibriMcpServer(): McpServer;
|
|
8
8
|
|
|
9
9
|
export { createKolibriMcpServer };
|
package/dist/mcp.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
|
4
4
|
* Create a configured KoliBri MCP server instance.
|
|
5
5
|
* Can be used with both stdio and HTTP transports.
|
|
6
6
|
*/
|
|
7
|
-
declare function createKolibriMcpServer():
|
|
7
|
+
declare function createKolibriMcpServer(): McpServer;
|
|
8
8
|
|
|
9
9
|
export { createKolibriMcpServer };
|
package/dist/mcp.mjs
CHANGED
|
@@ -5,11 +5,9 @@ import { createRequire } from 'node:module';
|
|
|
5
5
|
import { z } from 'zod';
|
|
6
6
|
import { getSampleIndexMetadata, getAllEntries, getEntryById } from './data.mjs';
|
|
7
7
|
import { searchEntries } from './search.mjs';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import simpleGit from 'simple-git';
|
|
12
|
-
import 'node:url';
|
|
8
|
+
import { readFileSync } from 'node:fs';
|
|
9
|
+
import { resolve } from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
13
11
|
import 'fuse.js';
|
|
14
12
|
|
|
15
13
|
const TEMPLATE_REPOS = [
|
|
@@ -51,151 +49,6 @@ const TEMPLATE_REPOS = [
|
|
|
51
49
|
}
|
|
52
50
|
];
|
|
53
51
|
|
|
54
|
-
const CACHE_DIR$1 = join(process.cwd(), "data", "templates");
|
|
55
|
-
async function cloneOrUpdateRepo(repoConfig) {
|
|
56
|
-
const repoPath = join(CACHE_DIR$1, repoConfig.id);
|
|
57
|
-
const git = simpleGit();
|
|
58
|
-
try {
|
|
59
|
-
const exists = await promises.access(repoPath).then(() => true).catch(() => false);
|
|
60
|
-
if (exists) {
|
|
61
|
-
await git.cwd(repoPath).pull();
|
|
62
|
-
console.log(`\u2705 Updated ${repoConfig.id}`);
|
|
63
|
-
} else {
|
|
64
|
-
await git.clone(`https://github.com/${repoConfig.owner}/${repoConfig.repo}.git`, repoPath, [
|
|
65
|
-
"--branch",
|
|
66
|
-
repoConfig.branch,
|
|
67
|
-
"--single-branch",
|
|
68
|
-
"--depth",
|
|
69
|
-
"1"
|
|
70
|
-
]);
|
|
71
|
-
console.log(`\u2705 Cloned ${repoConfig.id}`);
|
|
72
|
-
}
|
|
73
|
-
return repoPath;
|
|
74
|
-
} catch (error) {
|
|
75
|
-
console.error(`\u274C Error cloning/updating ${repoConfig.id}:`, error);
|
|
76
|
-
throw error;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
async function findFilesInRepo(repoPath, repoConfig) {
|
|
80
|
-
const allFiles = [];
|
|
81
|
-
for (const pattern of repoConfig.includePatterns) {
|
|
82
|
-
const files = await glob(pattern, {
|
|
83
|
-
cwd: repoPath,
|
|
84
|
-
ignore: repoConfig.excludePatterns,
|
|
85
|
-
nodir: true
|
|
86
|
-
});
|
|
87
|
-
allFiles.push(...files);
|
|
88
|
-
}
|
|
89
|
-
return [...new Set(allFiles)];
|
|
90
|
-
}
|
|
91
|
-
function getResourceType(filePath) {
|
|
92
|
-
if (filePath.endsWith(".md") || filePath.endsWith(".markdown")) {
|
|
93
|
-
return "markdown";
|
|
94
|
-
}
|
|
95
|
-
if (filePath.endsWith(".json") || filePath.endsWith(".yaml") || filePath.endsWith(".yml")) {
|
|
96
|
-
return "config";
|
|
97
|
-
}
|
|
98
|
-
return "code";
|
|
99
|
-
}
|
|
100
|
-
function getLanguage(filePath) {
|
|
101
|
-
const extension = filePath.split(".").pop()?.toLowerCase();
|
|
102
|
-
const languageMap = {
|
|
103
|
-
ts: "typescript",
|
|
104
|
-
tsx: "typescript",
|
|
105
|
-
js: "javascript",
|
|
106
|
-
jsx: "javascript",
|
|
107
|
-
css: "css",
|
|
108
|
-
scss: "scss",
|
|
109
|
-
html: "html",
|
|
110
|
-
json: "json",
|
|
111
|
-
yaml: "yaml",
|
|
112
|
-
yml: "yaml"
|
|
113
|
-
};
|
|
114
|
-
return languageMap[extension || ""] || extension || "unknown";
|
|
115
|
-
}
|
|
116
|
-
function extractFrontmatter(content) {
|
|
117
|
-
const frontmatterRegex = /^---[\s\S]*?---/;
|
|
118
|
-
const match = content.match(frontmatterRegex);
|
|
119
|
-
if (!match) return {};
|
|
120
|
-
try {
|
|
121
|
-
const frontmatter = match[0].replace(/^---|---$/g, "").trim();
|
|
122
|
-
const metadata = {};
|
|
123
|
-
frontmatter.split("\n").forEach((line) => {
|
|
124
|
-
const [key, value] = line.split(":").map((s) => s.trim());
|
|
125
|
-
if (key && value) {
|
|
126
|
-
metadata[key] = value.replace(/^['"]|['"]$/g, "");
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
return metadata;
|
|
130
|
-
} catch {
|
|
131
|
-
return {};
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async function indexFile(repoPath, filePath, repoConfig) {
|
|
135
|
-
const absolutePath = join(repoPath, filePath);
|
|
136
|
-
const content = await promises.readFile(absolutePath, "utf-8");
|
|
137
|
-
const stats = await promises.stat(absolutePath);
|
|
138
|
-
const resourceType = getResourceType(filePath);
|
|
139
|
-
const frontmatter = resourceType === "markdown" ? extractFrontmatter(content) : {};
|
|
140
|
-
const lines = content.split("\n").length;
|
|
141
|
-
return {
|
|
142
|
-
id: `${repoConfig.id}:${filePath.replace(/[/\\]/g, ":")}`,
|
|
143
|
-
repoId: repoConfig.id,
|
|
144
|
-
path: filePath,
|
|
145
|
-
type: resourceType,
|
|
146
|
-
content,
|
|
147
|
-
metadata: {
|
|
148
|
-
name: frontmatter.title || filePath.split("/").pop() || "",
|
|
149
|
-
description: frontmatter.description || void 0,
|
|
150
|
-
tags: [...repoConfig.tags || [], ...frontmatter.tags ?? []].filter((t) => t),
|
|
151
|
-
templateType: repoConfig.type,
|
|
152
|
-
language: resourceType === "code" ? getLanguage(filePath) : void 0
|
|
153
|
-
},
|
|
154
|
-
stats: {
|
|
155
|
-
size: stats.size,
|
|
156
|
-
lines,
|
|
157
|
-
lastModified: stats.mtime.toISOString()
|
|
158
|
-
}
|
|
159
|
-
};
|
|
160
|
-
}
|
|
161
|
-
async function indexTemplateRepo(repoConfig) {
|
|
162
|
-
console.log(`\u{1F4C1} Indexing ${repoConfig.id}...`);
|
|
163
|
-
const repoPath = await cloneOrUpdateRepo(repoConfig);
|
|
164
|
-
const files = await findFilesInRepo(repoPath, repoConfig);
|
|
165
|
-
console.log(` Found ${files.length} files to index`);
|
|
166
|
-
const resources = [];
|
|
167
|
-
for (const file of files) {
|
|
168
|
-
try {
|
|
169
|
-
const resource = await indexFile(repoPath, file, repoConfig);
|
|
170
|
-
resources.push(resource);
|
|
171
|
-
} catch (error) {
|
|
172
|
-
console.warn(` \u26A0\uFE0F Could not index ${file}:`, error);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
console.log(`\u2705 Indexed ${resources.length} resources from ${repoConfig.id}`);
|
|
176
|
-
return resources;
|
|
177
|
-
}
|
|
178
|
-
async function indexAllTemplateRepos() {
|
|
179
|
-
const allResources = [];
|
|
180
|
-
for (const repoConfig of TEMPLATE_REPOS) {
|
|
181
|
-
try {
|
|
182
|
-
const resources = await indexTemplateRepo(repoConfig);
|
|
183
|
-
allResources.push(...resources);
|
|
184
|
-
} catch (error) {
|
|
185
|
-
console.error(`\u274C Failed to index ${repoConfig.id}:`, error);
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
return allResources;
|
|
189
|
-
}
|
|
190
|
-
async function updateTemplateIndex() {
|
|
191
|
-
console.log("\u{1F504} Updating template index...");
|
|
192
|
-
const resources = await indexAllTemplateRepos();
|
|
193
|
-
const indexPath = join(CACHE_DIR$1, "template-index.json");
|
|
194
|
-
await promises.mkdir(CACHE_DIR$1, { recursive: true });
|
|
195
|
-
await promises.writeFile(indexPath, JSON.stringify(resources, null, 2));
|
|
196
|
-
console.log(`\u2705 Template index updated with ${resources.length} resources`);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
52
|
function extractCodeBlocksFromMarkdown(markdown) {
|
|
200
53
|
const codeBlockRegex = /```(\w*)\s*([\s\S]*?)```/g;
|
|
201
54
|
const blocks = [];
|
|
@@ -232,30 +85,31 @@ function calculateSimilarityScore(resource, query) {
|
|
|
232
85
|
return score;
|
|
233
86
|
}
|
|
234
87
|
|
|
235
|
-
|
|
88
|
+
function getIndexPath() {
|
|
89
|
+
const currentDir = fileURLToPath(new URL(".", import.meta.url));
|
|
90
|
+
if (currentDir.includes("/dist/")) {
|
|
91
|
+
return resolve(currentDir, "../shared/template-index.json");
|
|
92
|
+
}
|
|
93
|
+
return resolve(currentDir, "../../shared/template-index.json");
|
|
94
|
+
}
|
|
95
|
+
const INDEX_PATH = getIndexPath();
|
|
236
96
|
let templateIndex = [];
|
|
237
|
-
|
|
97
|
+
function loadTemplateIndex() {
|
|
238
98
|
try {
|
|
239
|
-
const
|
|
240
|
-
const content = await promises.readFile(indexPath, "utf-8");
|
|
99
|
+
const content = readFileSync(INDEX_PATH, "utf-8");
|
|
241
100
|
const parsed = JSON.parse(content);
|
|
242
101
|
return Array.isArray(parsed) ? parsed : [];
|
|
243
102
|
} catch {
|
|
244
103
|
return [];
|
|
245
104
|
}
|
|
246
105
|
}
|
|
247
|
-
|
|
106
|
+
function initializeTemplateIndex() {
|
|
248
107
|
console.log("\u{1F4DA} Initializing template index...");
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
templateIndex = await loadTemplateIndex();
|
|
254
|
-
}
|
|
108
|
+
templateIndex = loadTemplateIndex();
|
|
109
|
+
if (templateIndex.length === 0) {
|
|
110
|
+
console.warn("\u26A0\uFE0F Template index is empty. Run `pnpm update-templates` before building to include template data.");
|
|
111
|
+
} else {
|
|
255
112
|
console.log(`\u2705 Template index loaded with ${templateIndex.length} resources`);
|
|
256
|
-
} catch (error) {
|
|
257
|
-
console.error("\u274C Failed to initialize template index:", error);
|
|
258
|
-
templateIndex = [];
|
|
259
113
|
}
|
|
260
114
|
}
|
|
261
115
|
function searchTemplates(query, options = {}) {
|
|
@@ -331,16 +185,16 @@ function log(type, message, data) {
|
|
|
331
185
|
console.error(`${prefix} ${message}`);
|
|
332
186
|
}
|
|
333
187
|
}
|
|
334
|
-
|
|
188
|
+
function createKolibriMcpServer() {
|
|
335
189
|
const server = new McpServer({
|
|
336
190
|
name: PACKAGE_NAME,
|
|
337
191
|
version: PACKAGE_VERSION
|
|
338
192
|
});
|
|
339
193
|
return configureServer(server);
|
|
340
194
|
}
|
|
341
|
-
|
|
195
|
+
function configureServer(server) {
|
|
342
196
|
try {
|
|
343
|
-
|
|
197
|
+
initializeTemplateIndex();
|
|
344
198
|
} catch (error) {
|
|
345
199
|
console.error("Failed to initialize template index:", error);
|
|
346
200
|
}
|
|
@@ -737,8 +591,8 @@ Use the 'fetch' tool to retrieve full code samples for specific components.
|
|
|
737
591
|
return server;
|
|
738
592
|
}
|
|
739
593
|
if (import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith("/mcp.ts") || process.argv[1]?.endsWith("/mcp.cjs") || process.argv[1]?.endsWith("/mcp.mjs")) {
|
|
740
|
-
void (
|
|
741
|
-
const server =
|
|
594
|
+
void (() => {
|
|
595
|
+
const server = createKolibriMcpServer();
|
|
742
596
|
const app = express();
|
|
743
597
|
app.use(express.json());
|
|
744
598
|
app.post("/mcp", async (req, res) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@public-ui/mcp",
|
|
3
|
-
"version": "4.3.0
|
|
3
|
+
"version": "4.3.0",
|
|
4
4
|
"license": "EUPL-1.2",
|
|
5
5
|
"homepage": "https://public-ui.github.io",
|
|
6
6
|
"repository": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"react",
|
|
30
30
|
"typescript"
|
|
31
31
|
],
|
|
32
|
-
"main": "dist/
|
|
33
|
-
"module": "dist/
|
|
32
|
+
"main": "dist/mcp.cjs",
|
|
33
|
+
"module": "dist/mcp.mjs",
|
|
34
34
|
"bin": {
|
|
35
35
|
"@public-ui/mcp": "dist/cli.cjs",
|
|
36
36
|
"kolibri-mcp": "dist/cli.cjs"
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"glob": "13.0.6",
|
|
49
49
|
"simple-git": "3.36.0",
|
|
50
50
|
"zod": "4.4.3",
|
|
51
|
-
"@public-ui/components": "4.3.0
|
|
51
|
+
"@public-ui/components": "4.3.0"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@modelcontextprotocol/inspector": "2.0.0",
|
|
@@ -72,16 +72,16 @@
|
|
|
72
72
|
"scripts": {
|
|
73
73
|
"build:deps": "pnpm --filter @public-ui/mcp^... build",
|
|
74
74
|
"generate-index": "node ./scripts/generate-sample-index.mjs",
|
|
75
|
-
"
|
|
76
|
-
"prebuild": "pnpm generate-index",
|
|
75
|
+
"generate-templates-index": "tsx ./scripts/generate-templates-index.mjs",
|
|
76
|
+
"prebuild": "pnpm generate-index && pnpm generate-templates-index",
|
|
77
77
|
"build": "unbuild",
|
|
78
|
-
"predev": "pnpm generate-index",
|
|
78
|
+
"predev": "pnpm generate-index && pnpm generate-templates-index",
|
|
79
79
|
"dev": "nodemon",
|
|
80
80
|
"format": "prettier -c src test public",
|
|
81
81
|
"lint": "pnpm lint:eslint && pnpm lint:tsc",
|
|
82
82
|
"lint:eslint": "eslint src test",
|
|
83
83
|
"lint:tsc": "tsc --noemit",
|
|
84
|
-
"preinspect": "pnpm generate-index",
|
|
84
|
+
"preinspect": "pnpm generate-index && pnpm generate-templates-index",
|
|
85
85
|
"inspect": "mcp-inspector tsx src/cli.ts",
|
|
86
86
|
"prestart": "pnpm build",
|
|
87
87
|
"start": "node dist/mcp.cjs",
|
package/shared/sample-index.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"metadata": {
|
|
3
|
-
"generatedAt": "2026-08-
|
|
3
|
+
"generatedAt": "2026-08-04T07:01:02.072Z",
|
|
4
4
|
"buildMode": "ci",
|
|
5
5
|
"counts": {
|
|
6
6
|
"total": 331,
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"totalScenarios": 19
|
|
11
11
|
},
|
|
12
12
|
"repo": {
|
|
13
|
-
"commit": "
|
|
13
|
+
"commit": "20cc9e1b0f92ab83d703454475728013f0350ac5",
|
|
14
14
|
"branch": "develop",
|
|
15
15
|
"repoUrl": "https://github.com/public-ui/kolibri"
|
|
16
16
|
}
|