@veolab/discoverylab 1.4.4 → 1.6.5
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/README.md +70 -211
- package/assets/applab-bundle-icon.png +0 -0
- package/assets/icons/icons8-claude-150.png +0 -0
- package/assets/icons/icons8-claude-500.png +0 -0
- package/dist/{chunk-CUBQRT5L.js → chunk-JAA53ES7.js} +111 -2
- package/dist/{chunk-HB3YPWF3.js → chunk-Q7Q3A2ZI.js} +301 -10
- package/dist/{chunk-XKX6NBHF.js → chunk-TWRWARU4.js} +52 -2
- package/dist/{chunk-2UUMLAVR.js → chunk-V6RREMYD.js} +332 -38
- package/dist/cli.js +164 -28
- package/dist/export/infographic-template.html +254 -0
- package/dist/import-W2JEW254.js +180 -0
- package/dist/index.d.ts +30 -6
- package/dist/index.html +473 -11
- package/dist/index.js +5 -5
- package/dist/infographic-GQAHEOAA.js +183 -0
- package/dist/mcpb/node_modules/@anthropic-ai/sdk/src/lib/.keep +4 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/better_sqlite3.node.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/better_sqlite3/src/better_sqlite3.o.d +133 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/deps/locate_sqlite3.stamp.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/sqlite3/gen/sqlite3/sqlite3.o.d +4 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/obj.target/test_extension/deps/test_extension.o.d +7 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/sqlite3.a.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/Release/test_extension.node.d +1 -0
- package/dist/mcpb/node_modules/better-sqlite3/build/Release/.deps/ba23eeee118cd63e16015df367567cb043fed872.intermediate.d +1 -0
- package/dist/{server-QFNKZCOJ.js → server-C2NZM2RV.js} +1 -1
- package/dist/{server-OVOACIOJ.js → server-WN6DCCUA.js} +1 -1
- package/dist/{setup-6JJYKKBS.js → setup-SMN7FJNZ.js} +5 -2
- package/dist/{tools-Q7OZO732.js → tools-VXU3JEQP.js} +6 -4
- package/doc/esvp-protocol.md +116 -0
- package/package.json +9 -3
- package/skills/knowledge-brain/SKILL.md +44 -43
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
import {
|
|
2
|
+
checkNotionAuth,
|
|
3
|
+
createNotionPage,
|
|
4
|
+
loginToNotion,
|
|
5
|
+
quickExportToNotion
|
|
6
|
+
} from "./chunk-34GGYFXX.js";
|
|
1
7
|
import {
|
|
2
8
|
detectKeyFrames,
|
|
3
9
|
extractFrames,
|
|
@@ -8,14 +14,9 @@ import {
|
|
|
8
14
|
import {
|
|
9
15
|
createErrorResult,
|
|
10
16
|
createJsonResult,
|
|
11
|
-
createTextResult
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
checkNotionAuth,
|
|
15
|
-
createNotionPage,
|
|
16
|
-
loginToNotion,
|
|
17
|
-
quickExportToNotion
|
|
18
|
-
} from "./chunk-34GGYFXX.js";
|
|
17
|
+
createTextResult,
|
|
18
|
+
mcpServer
|
|
19
|
+
} from "./chunk-TWRWARU4.js";
|
|
19
20
|
import {
|
|
20
21
|
getAvailableTemplates,
|
|
21
22
|
isTemplatesInstalled
|
|
@@ -3776,6 +3777,93 @@ var exportSequenceTool = {
|
|
|
3776
3777
|
}, null, 2));
|
|
3777
3778
|
}
|
|
3778
3779
|
};
|
|
3780
|
+
var exportInfographicTool = {
|
|
3781
|
+
name: "dlab.export.infographic",
|
|
3782
|
+
description: "Export a DiscoveryLab project as an interactive HTML infographic. Generates a self-contained offline HTML file with animated frame player, hotspots, annotations, and baseline status.",
|
|
3783
|
+
inputSchema: z6.object({
|
|
3784
|
+
projectId: z6.string().describe("Project ID"),
|
|
3785
|
+
open: z6.boolean().optional().describe("Open in browser after export"),
|
|
3786
|
+
outputPath: z6.string().optional().describe("Custom output directory")
|
|
3787
|
+
}),
|
|
3788
|
+
handler: async (params) => {
|
|
3789
|
+
try {
|
|
3790
|
+
const { projects: projectsTable, frames: framesTable, FRAMES_DIR, PROJECTS_DIR: PROJECTS_DIR3 } = await import("./db-5ECN3O7F.js");
|
|
3791
|
+
const { eq: eq4 } = await import("drizzle-orm");
|
|
3792
|
+
const { collectFrameImages, buildInfographicData, generateInfographicHtml } = await import("./infographic-GQAHEOAA.js");
|
|
3793
|
+
const db = getDatabase();
|
|
3794
|
+
const [project] = await db.select().from(projectsTable).where(eq4(projectsTable.id, params.projectId)).limit(1);
|
|
3795
|
+
if (!project) return createErrorResult(`Project not found: ${params.projectId}`);
|
|
3796
|
+
const dbFrames = await db.select().from(framesTable).where(eq4(framesTable.projectId, project.id)).orderBy(framesTable.frameNumber).limit(20);
|
|
3797
|
+
let frameFiles;
|
|
3798
|
+
let frameOcr;
|
|
3799
|
+
if (dbFrames.length > 0) {
|
|
3800
|
+
frameFiles = dbFrames.map((f) => f.imagePath);
|
|
3801
|
+
frameOcr = dbFrames;
|
|
3802
|
+
} else {
|
|
3803
|
+
frameFiles = collectFrameImages(
|
|
3804
|
+
path5.join(FRAMES_DIR, project.id),
|
|
3805
|
+
project.videoPath,
|
|
3806
|
+
PROJECTS_DIR3,
|
|
3807
|
+
project.id
|
|
3808
|
+
);
|
|
3809
|
+
frameOcr = frameFiles.map(() => ({ ocrText: null }));
|
|
3810
|
+
}
|
|
3811
|
+
if (frameFiles.length === 0) {
|
|
3812
|
+
return createErrorResult("No frames found. Run analyzer first.");
|
|
3813
|
+
}
|
|
3814
|
+
const data = buildInfographicData(project, frameFiles, frameOcr);
|
|
3815
|
+
const slug = (project.marketingTitle || project.name || project.id).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "").slice(0, 40);
|
|
3816
|
+
const outputFilePath = params.outputPath ? path5.join(params.outputPath, `${slug}-infographic.html`) : path5.join(EXPORTS_DIR, `${slug}-infographic.html`);
|
|
3817
|
+
const result = generateInfographicHtml(data, outputFilePath);
|
|
3818
|
+
if (!result.success) {
|
|
3819
|
+
return createErrorResult(`Export failed: ${result.error}`);
|
|
3820
|
+
}
|
|
3821
|
+
if (params.open) {
|
|
3822
|
+
const { exec: exec5 } = await import("child_process");
|
|
3823
|
+
exec5(`open "${result.outputPath}"`);
|
|
3824
|
+
}
|
|
3825
|
+
const sizeKb = ((result.size || 0) / 1024).toFixed(1);
|
|
3826
|
+
return createTextResult(`Infographic exported!
|
|
3827
|
+
|
|
3828
|
+
Path: ${result.outputPath}
|
|
3829
|
+
Size: ${sizeKb}KB
|
|
3830
|
+
Frames: ${result.frameCount}
|
|
3831
|
+
|
|
3832
|
+
Open in any browser to view.`);
|
|
3833
|
+
} catch (error) {
|
|
3834
|
+
return createErrorResult(`Export failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3835
|
+
}
|
|
3836
|
+
}
|
|
3837
|
+
};
|
|
3838
|
+
var importProjectTool = {
|
|
3839
|
+
name: "dlab.project.import",
|
|
3840
|
+
description: "Import a shared .applab project bundle file. Use this when someone shares a .applab file with you.",
|
|
3841
|
+
inputSchema: z6.object({
|
|
3842
|
+
filePath: z6.string().describe("Path to the .applab file")
|
|
3843
|
+
}),
|
|
3844
|
+
handler: async (params) => {
|
|
3845
|
+
try {
|
|
3846
|
+
const { projects: projectsTable, frames: framesTable, DATA_DIR: DATA_DIR2, FRAMES_DIR, PROJECTS_DIR: PROJECTS_DIR3 } = await import("./db-5ECN3O7F.js");
|
|
3847
|
+
const { importApplabBundle } = await import("./import-W2JEW254.js");
|
|
3848
|
+
const db = getDatabase();
|
|
3849
|
+
const result = await importApplabBundle(params.filePath, db, { projects: projectsTable, frames: framesTable }, {
|
|
3850
|
+
dataDir: DATA_DIR2,
|
|
3851
|
+
framesDir: FRAMES_DIR,
|
|
3852
|
+
projectsDir: PROJECTS_DIR3
|
|
3853
|
+
});
|
|
3854
|
+
if (!result.success) return createErrorResult(`Import failed: ${result.error}`);
|
|
3855
|
+
return createTextResult(`Project imported!
|
|
3856
|
+
|
|
3857
|
+
Name: ${result.projectName}
|
|
3858
|
+
ID: ${result.projectId}
|
|
3859
|
+
Frames: ${result.frameCount}
|
|
3860
|
+
|
|
3861
|
+
Use dlab.knowledge.search to query this project.`);
|
|
3862
|
+
} catch (error) {
|
|
3863
|
+
return createErrorResult(`Import failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
3864
|
+
}
|
|
3865
|
+
}
|
|
3866
|
+
};
|
|
3779
3867
|
var exportTools = [
|
|
3780
3868
|
exportVideoTool,
|
|
3781
3869
|
exportGifTool,
|
|
@@ -3788,7 +3876,9 @@ var exportTools = [
|
|
|
3788
3876
|
exportInfoTool,
|
|
3789
3877
|
exportClipboardTool,
|
|
3790
3878
|
exportRevealTool,
|
|
3791
|
-
exportSequenceTool
|
|
3879
|
+
exportSequenceTool,
|
|
3880
|
+
exportInfographicTool,
|
|
3881
|
+
importProjectTool
|
|
3792
3882
|
];
|
|
3793
3883
|
|
|
3794
3884
|
// src/mcp/tools/testing.ts
|
|
@@ -6830,6 +6920,102 @@ var templateTools = [
|
|
|
6830
6920
|
// src/mcp/tools/knowledge.ts
|
|
6831
6921
|
import { z as z12 } from "zod";
|
|
6832
6922
|
import { desc as desc2 } from "drizzle-orm";
|
|
6923
|
+
var KNOWLEDGE_VIEWER_RESOURCE_URI = "ui://discoverylab/knowledge-viewer.html";
|
|
6924
|
+
var KNOWLEDGE_VIEWER_MIME_TYPE = "text/html;profile=mcp-app";
|
|
6925
|
+
function buildViewerPlaceholderHtml(message) {
|
|
6926
|
+
const safeMessage = JSON.stringify(message);
|
|
6927
|
+
return `<!DOCTYPE html>
|
|
6928
|
+
<html lang="en">
|
|
6929
|
+
<head>
|
|
6930
|
+
<meta charset="UTF-8" />
|
|
6931
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6932
|
+
<title>DiscoveryLab Flow Viewer</title>
|
|
6933
|
+
<style>
|
|
6934
|
+
:root {
|
|
6935
|
+
color-scheme: dark;
|
|
6936
|
+
--bg: #0b1117;
|
|
6937
|
+
--panel: rgba(255, 255, 255, 0.04);
|
|
6938
|
+
--border: rgba(255, 255, 255, 0.1);
|
|
6939
|
+
--text: #eff5fb;
|
|
6940
|
+
--muted: #9fb0c2;
|
|
6941
|
+
--accent: #2dd4bf;
|
|
6942
|
+
}
|
|
6943
|
+
|
|
6944
|
+
* { box-sizing: border-box; }
|
|
6945
|
+
|
|
6946
|
+
body {
|
|
6947
|
+
margin: 0;
|
|
6948
|
+
min-height: 100vh;
|
|
6949
|
+
display: grid;
|
|
6950
|
+
place-items: center;
|
|
6951
|
+
padding: 24px;
|
|
6952
|
+
background:
|
|
6953
|
+
radial-gradient(circle at top left, rgba(45, 212, 191, 0.18), transparent 28%),
|
|
6954
|
+
linear-gradient(180deg, #101826, var(--bg));
|
|
6955
|
+
color: var(--text);
|
|
6956
|
+
font: 14px/1.5 "IBM Plex Sans", "Segoe UI", system-ui, sans-serif;
|
|
6957
|
+
}
|
|
6958
|
+
|
|
6959
|
+
.card {
|
|
6960
|
+
width: min(720px, 100%);
|
|
6961
|
+
border: 1px solid var(--border);
|
|
6962
|
+
border-radius: 24px;
|
|
6963
|
+
padding: 24px;
|
|
6964
|
+
background: var(--panel);
|
|
6965
|
+
box-shadow: 0 24px 60px rgba(0, 0, 0, 0.28);
|
|
6966
|
+
}
|
|
6967
|
+
|
|
6968
|
+
.eyebrow {
|
|
6969
|
+
display: inline-flex;
|
|
6970
|
+
align-items: center;
|
|
6971
|
+
gap: 8px;
|
|
6972
|
+
border: 1px solid var(--border);
|
|
6973
|
+
border-radius: 999px;
|
|
6974
|
+
padding: 6px 12px;
|
|
6975
|
+
color: var(--muted);
|
|
6976
|
+
font-size: 12px;
|
|
6977
|
+
text-transform: uppercase;
|
|
6978
|
+
letter-spacing: 0.03em;
|
|
6979
|
+
}
|
|
6980
|
+
|
|
6981
|
+
h1 {
|
|
6982
|
+
margin: 16px 0 8px;
|
|
6983
|
+
font: 700 32px/1.02 "Space Grotesk", "Avenir Next", system-ui, sans-serif;
|
|
6984
|
+
letter-spacing: -0.03em;
|
|
6985
|
+
}
|
|
6986
|
+
|
|
6987
|
+
p {
|
|
6988
|
+
margin: 0;
|
|
6989
|
+
color: var(--muted);
|
|
6990
|
+
}
|
|
6991
|
+
</style>
|
|
6992
|
+
</head>
|
|
6993
|
+
<body>
|
|
6994
|
+
<main class="card">
|
|
6995
|
+
<div class="eyebrow">DiscoveryLab Local Viewer</div>
|
|
6996
|
+
<h1>Open a flow in Claude Desktop</h1>
|
|
6997
|
+
<p id="message"></p>
|
|
6998
|
+
</main>
|
|
6999
|
+
<script>
|
|
7000
|
+
document.getElementById('message').textContent = ${safeMessage};
|
|
7001
|
+
</script>
|
|
7002
|
+
</body>
|
|
7003
|
+
</html>`;
|
|
7004
|
+
}
|
|
7005
|
+
mcpServer.registerResource({
|
|
7006
|
+
uri: KNOWLEDGE_VIEWER_RESOURCE_URI,
|
|
7007
|
+
name: "discoverylab-knowledge-viewer",
|
|
7008
|
+
title: "DiscoveryLab Flow Viewer",
|
|
7009
|
+
description: "Interactive local flow viewer for DiscoveryLab projects.",
|
|
7010
|
+
mimeType: KNOWLEDGE_VIEWER_MIME_TYPE,
|
|
7011
|
+
contents: [
|
|
7012
|
+
{
|
|
7013
|
+
uri: KNOWLEDGE_VIEWER_RESOURCE_URI,
|
|
7014
|
+
mimeType: KNOWLEDGE_VIEWER_MIME_TYPE,
|
|
7015
|
+
text: buildViewerPlaceholderHtml("Use dlab.knowledge.open to load a local project into the canvas.")
|
|
7016
|
+
}
|
|
7017
|
+
]
|
|
7018
|
+
});
|
|
6833
7019
|
var knowledgeSearchTool = {
|
|
6834
7020
|
name: "dlab.knowledge.search",
|
|
6835
7021
|
description: `Search across all DiscoveryLab projects for app flows, UI elements, screens, and behaviors. Use this when the user asks about how an app works, what a specific screen looks like, or any question about captured app flows. Returns relevant projects with their analysis, OCR text, and context.`,
|
|
@@ -6997,9 +7183,114 @@ Use \`dlab.knowledge.search\` with a query to find specific flows or screens.`;
|
|
|
6997
7183
|
}
|
|
6998
7184
|
}
|
|
6999
7185
|
};
|
|
7186
|
+
var knowledgeOpenTool = {
|
|
7187
|
+
name: "dlab.knowledge.open",
|
|
7188
|
+
description: `Open an interactive visual infographic of an app flow. Returns self-contained HTML that Claude Desktop renders as a canvas/artifact. Use this when the user wants to SEE a flow visually, not just read about it. The HTML includes animated frame player, annotations, and navigation.`,
|
|
7189
|
+
inputSchema: z12.object({
|
|
7190
|
+
query: z12.string().optional().describe('Search query to find the project (e.g. "login flow", "onboarding")'),
|
|
7191
|
+
projectId: z12.string().optional().describe("Direct project ID if known")
|
|
7192
|
+
}),
|
|
7193
|
+
_meta: {
|
|
7194
|
+
ui: {
|
|
7195
|
+
resourceUri: KNOWLEDGE_VIEWER_RESOURCE_URI
|
|
7196
|
+
}
|
|
7197
|
+
},
|
|
7198
|
+
handler: async (params) => {
|
|
7199
|
+
try {
|
|
7200
|
+
const db = getDatabase();
|
|
7201
|
+
let project = null;
|
|
7202
|
+
if (params.projectId) {
|
|
7203
|
+
const { eq: eq5 } = await import("drizzle-orm");
|
|
7204
|
+
const [p] = await db.select().from(projects).where(eq5(projects.id, params.projectId)).limit(1);
|
|
7205
|
+
project = p;
|
|
7206
|
+
} else if (params.query) {
|
|
7207
|
+
const allProjects = await db.select().from(projects).orderBy(desc2(projects.updatedAt));
|
|
7208
|
+
const query = params.query.toLowerCase();
|
|
7209
|
+
const queryTerms = query.split(/\s+/).filter((t) => t.length > 1);
|
|
7210
|
+
let bestScore = 0;
|
|
7211
|
+
for (const p of allProjects) {
|
|
7212
|
+
let score = 0;
|
|
7213
|
+
const fields = [p.name, p.marketingTitle, p.aiSummary, p.ocrText, p.tags, p.linkedTicket].filter(Boolean);
|
|
7214
|
+
for (const field of fields) {
|
|
7215
|
+
const text = field.toLowerCase();
|
|
7216
|
+
for (const term of queryTerms) {
|
|
7217
|
+
if (text.includes(term)) score += 1;
|
|
7218
|
+
}
|
|
7219
|
+
if (text.includes(query)) score += 3;
|
|
7220
|
+
}
|
|
7221
|
+
if (score > bestScore) {
|
|
7222
|
+
bestScore = score;
|
|
7223
|
+
project = p;
|
|
7224
|
+
}
|
|
7225
|
+
}
|
|
7226
|
+
}
|
|
7227
|
+
if (!project) {
|
|
7228
|
+
return createErrorResult(`No project found${params.query ? ` for "${params.query}"` : ""}. Use dlab.knowledge.summary to see available projects.`);
|
|
7229
|
+
}
|
|
7230
|
+
const { eq: eq4 } = await import("drizzle-orm");
|
|
7231
|
+
const { FRAMES_DIR, PROJECTS_DIR: PROJECTS_DIR3 } = await import("./db-5ECN3O7F.js");
|
|
7232
|
+
const { join: join12 } = await import("path");
|
|
7233
|
+
const dbFrames = await db.select().from(frames).where(eq4(frames.projectId, project.id)).orderBy(frames.frameNumber).limit(15);
|
|
7234
|
+
let frameFiles;
|
|
7235
|
+
let frameOcr;
|
|
7236
|
+
if (dbFrames.length > 0) {
|
|
7237
|
+
frameFiles = dbFrames.map((f) => f.imagePath);
|
|
7238
|
+
frameOcr = dbFrames;
|
|
7239
|
+
} else {
|
|
7240
|
+
const { collectFrameImages } = await import("./infographic-GQAHEOAA.js");
|
|
7241
|
+
frameFiles = collectFrameImages(join12(FRAMES_DIR, project.id), project.videoPath, PROJECTS_DIR3, project.id);
|
|
7242
|
+
frameOcr = frameFiles.map(() => ({ ocrText: null }));
|
|
7243
|
+
}
|
|
7244
|
+
if (frameFiles.length === 0) {
|
|
7245
|
+
return createTextResult(`Project "${project.marketingTitle || project.name}" has no frames. Run the analyzer first, then try again.`);
|
|
7246
|
+
}
|
|
7247
|
+
const { buildInfographicData, generateInfographicHtmlString } = await import("./infographic-GQAHEOAA.js");
|
|
7248
|
+
const data = buildInfographicData(project, frameFiles, frameOcr);
|
|
7249
|
+
const html = generateInfographicHtmlString(data);
|
|
7250
|
+
if (!html) {
|
|
7251
|
+
return createErrorResult("Failed to generate infographic HTML (template not found)");
|
|
7252
|
+
}
|
|
7253
|
+
mcpServer.upsertResourceContents(KNOWLEDGE_VIEWER_RESOURCE_URI, {
|
|
7254
|
+
name: "discoverylab-knowledge-viewer",
|
|
7255
|
+
title: `DiscoveryLab Flow Viewer \xB7 ${project.marketingTitle || project.name}`,
|
|
7256
|
+
description: "Interactive local flow viewer for DiscoveryLab projects.",
|
|
7257
|
+
mimeType: KNOWLEDGE_VIEWER_MIME_TYPE,
|
|
7258
|
+
contents: [
|
|
7259
|
+
{
|
|
7260
|
+
uri: KNOWLEDGE_VIEWER_RESOURCE_URI,
|
|
7261
|
+
mimeType: KNOWLEDGE_VIEWER_MIME_TYPE,
|
|
7262
|
+
text: html
|
|
7263
|
+
}
|
|
7264
|
+
]
|
|
7265
|
+
});
|
|
7266
|
+
return {
|
|
7267
|
+
content: [
|
|
7268
|
+
{
|
|
7269
|
+
type: "text",
|
|
7270
|
+
text: `Opened the local DiscoveryLab flow viewer for ${project.marketingTitle || project.name}.`
|
|
7271
|
+
}
|
|
7272
|
+
],
|
|
7273
|
+
structuredContent: {
|
|
7274
|
+
projectId: project.id,
|
|
7275
|
+
name: project.marketingTitle || project.name,
|
|
7276
|
+
frameCount: frameFiles.length,
|
|
7277
|
+
platform: project.platform || "unknown"
|
|
7278
|
+
},
|
|
7279
|
+
_meta: {
|
|
7280
|
+
ui: {
|
|
7281
|
+
resourceUri: KNOWLEDGE_VIEWER_RESOURCE_URI
|
|
7282
|
+
}
|
|
7283
|
+
}
|
|
7284
|
+
};
|
|
7285
|
+
} catch (error) {
|
|
7286
|
+
return createErrorResult(`Failed to open flow: ${error instanceof Error ? error.message : String(error)}`);
|
|
7287
|
+
}
|
|
7288
|
+
}
|
|
7289
|
+
};
|
|
7000
7290
|
var knowledgeTools = [
|
|
7001
7291
|
knowledgeSearchTool,
|
|
7002
|
-
knowledgeSummaryTool
|
|
7292
|
+
knowledgeSummaryTool,
|
|
7293
|
+
knowledgeOpenTool
|
|
7003
7294
|
];
|
|
7004
7295
|
|
|
7005
7296
|
export {
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
var MCPServer = class {
|
|
8
8
|
tools = /* @__PURE__ */ new Map();
|
|
9
|
+
resources = /* @__PURE__ */ new Map();
|
|
9
10
|
serverInfo = {
|
|
10
11
|
name: "discoverylab",
|
|
11
12
|
version: APP_VERSION
|
|
@@ -18,6 +19,15 @@ var MCPServer = class {
|
|
|
18
19
|
this.registerTool(tool);
|
|
19
20
|
}
|
|
20
21
|
}
|
|
22
|
+
registerResource(resource) {
|
|
23
|
+
this.resources.set(resource.uri, resource);
|
|
24
|
+
}
|
|
25
|
+
upsertResourceContents(uri, resource) {
|
|
26
|
+
this.resources.set(uri, {
|
|
27
|
+
uri,
|
|
28
|
+
...resource
|
|
29
|
+
});
|
|
30
|
+
}
|
|
21
31
|
async handleRequest(request) {
|
|
22
32
|
const { id, method, params } = request;
|
|
23
33
|
try {
|
|
@@ -28,6 +38,10 @@ var MCPServer = class {
|
|
|
28
38
|
return this.handleToolsList(id);
|
|
29
39
|
case "tools/call":
|
|
30
40
|
return this.handleToolCall(id, params);
|
|
41
|
+
case "resources/list":
|
|
42
|
+
return this.handleResourcesList(id);
|
|
43
|
+
case "resources/read":
|
|
44
|
+
return this.handleResourcesRead(id, params);
|
|
31
45
|
case "ping":
|
|
32
46
|
return { jsonrpc: "2.0", id, result: { pong: true } };
|
|
33
47
|
default:
|
|
@@ -54,7 +68,8 @@ var MCPServer = class {
|
|
|
54
68
|
protocolVersion: "2024-11-05",
|
|
55
69
|
serverInfo: this.serverInfo,
|
|
56
70
|
capabilities: {
|
|
57
|
-
tools: {}
|
|
71
|
+
tools: {},
|
|
72
|
+
resources: {}
|
|
58
73
|
}
|
|
59
74
|
}
|
|
60
75
|
};
|
|
@@ -63,7 +78,8 @@ var MCPServer = class {
|
|
|
63
78
|
const tools = Array.from(this.tools.values()).map((tool) => ({
|
|
64
79
|
name: tool.name,
|
|
65
80
|
description: tool.description,
|
|
66
|
-
inputSchema: this.zodToJsonSchema(tool.inputSchema)
|
|
81
|
+
inputSchema: this.zodToJsonSchema(tool.inputSchema),
|
|
82
|
+
...tool._meta ? { _meta: tool._meta } : {}
|
|
67
83
|
}));
|
|
68
84
|
return {
|
|
69
85
|
jsonrpc: "2.0",
|
|
@@ -71,6 +87,40 @@ var MCPServer = class {
|
|
|
71
87
|
result: { tools }
|
|
72
88
|
};
|
|
73
89
|
}
|
|
90
|
+
handleResourcesList(id) {
|
|
91
|
+
const resources = Array.from(this.resources.values()).map((resource) => ({
|
|
92
|
+
uri: resource.uri,
|
|
93
|
+
name: resource.name,
|
|
94
|
+
...resource.title ? { title: resource.title } : {},
|
|
95
|
+
...resource.description ? { description: resource.description } : {},
|
|
96
|
+
mimeType: resource.mimeType
|
|
97
|
+
}));
|
|
98
|
+
return {
|
|
99
|
+
jsonrpc: "2.0",
|
|
100
|
+
id,
|
|
101
|
+
result: { resources }
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
handleResourcesRead(id, params) {
|
|
105
|
+
const uri = typeof params?.uri === "string" ? params.uri : "";
|
|
106
|
+
const resource = this.resources.get(uri);
|
|
107
|
+
if (!resource) {
|
|
108
|
+
return {
|
|
109
|
+
jsonrpc: "2.0",
|
|
110
|
+
id,
|
|
111
|
+
error: { code: -32602, message: `Resource not found: ${uri}` }
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
const contents = Array.isArray(resource.contents) && resource.contents.length > 0 ? resource.contents : [{
|
|
115
|
+
uri: resource.uri,
|
|
116
|
+
mimeType: resource.mimeType
|
|
117
|
+
}];
|
|
118
|
+
return {
|
|
119
|
+
jsonrpc: "2.0",
|
|
120
|
+
id,
|
|
121
|
+
result: { contents }
|
|
122
|
+
};
|
|
123
|
+
}
|
|
74
124
|
async handleToolCall(id, params) {
|
|
75
125
|
const { name, arguments: args } = params;
|
|
76
126
|
const tool = this.tools.get(name);
|