@contiva/sapbtp-docs-mcp 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +395 -0
- package/README.md +386 -0
- package/build/cache/embedding-cache.d.ts +39 -0
- package/build/cache/embedding-cache.d.ts.map +1 -0
- package/build/cache/embedding-cache.js +105 -0
- package/build/cache/embedding-cache.js.map +1 -0
- package/build/cache/file-cache.d.ts +40 -0
- package/build/cache/file-cache.d.ts.map +1 -0
- package/build/cache/file-cache.js +124 -0
- package/build/cache/file-cache.js.map +1 -0
- package/build/cache/search-cache.d.ts +39 -0
- package/build/cache/search-cache.d.ts.map +1 -0
- package/build/cache/search-cache.js +97 -0
- package/build/cache/search-cache.js.map +1 -0
- package/build/index.d.ts +3 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +17 -0
- package/build/index.js.map +1 -0
- package/build/indexing/file-registry.d.ts +47 -0
- package/build/indexing/file-registry.d.ts.map +1 -0
- package/build/indexing/file-registry.js +130 -0
- package/build/indexing/file-registry.js.map +1 -0
- package/build/indexing/topic-index.d.ts +57 -0
- package/build/indexing/topic-index.d.ts.map +1 -0
- package/build/indexing/topic-index.js +181 -0
- package/build/indexing/topic-index.js.map +1 -0
- package/build/parsers/links.d.ts +14 -0
- package/build/parsers/links.d.ts.map +1 -0
- package/build/parsers/links.js +80 -0
- package/build/parsers/links.js.map +1 -0
- package/build/parsers/markdown.d.ts +10 -0
- package/build/parsers/markdown.d.ts.map +1 -0
- package/build/parsers/markdown.js +120 -0
- package/build/parsers/markdown.js.map +1 -0
- package/build/parsers/metadata.d.ts +19 -0
- package/build/parsers/metadata.d.ts.map +1 -0
- package/build/parsers/metadata.js +63 -0
- package/build/parsers/metadata.js.map +1 -0
- package/build/search/fulltext.d.ts +20 -0
- package/build/search/fulltext.d.ts.map +1 -0
- package/build/search/fulltext.js +117 -0
- package/build/search/fulltext.js.map +1 -0
- package/build/search/ranking.d.ts +27 -0
- package/build/search/ranking.d.ts.map +1 -0
- package/build/search/ranking.js +119 -0
- package/build/search/ranking.js.map +1 -0
- package/build/search/semantic.d.ts +53 -0
- package/build/search/semantic.d.ts.map +1 -0
- package/build/search/semantic.js +260 -0
- package/build/search/semantic.js.map +1 -0
- package/build/search/title.d.ts +18 -0
- package/build/search/title.d.ts.map +1 -0
- package/build/search/title.js +95 -0
- package/build/search/title.js.map +1 -0
- package/build/server.d.ts +32 -0
- package/build/server.d.ts.map +1 -0
- package/build/server.js +183 -0
- package/build/server.js.map +1 -0
- package/build/tools/get-related.d.ts +64 -0
- package/build/tools/get-related.d.ts.map +1 -0
- package/build/tools/get-related.js +203 -0
- package/build/tools/get-related.js.map +1 -0
- package/build/tools/list-topics.d.ts +43 -0
- package/build/tools/list-topics.d.ts.map +1 -0
- package/build/tools/list-topics.js +63 -0
- package/build/tools/list-topics.js.map +1 -0
- package/build/tools/read-article.d.ts +42 -0
- package/build/tools/read-article.d.ts.map +1 -0
- package/build/tools/read-article.js +89 -0
- package/build/tools/read-article.js.map +1 -0
- package/build/tools/search.d.ts +57 -0
- package/build/tools/search.d.ts.map +1 -0
- package/build/tools/search.js +109 -0
- package/build/tools/search.js.map +1 -0
- package/build/types/index.d.ts +179 -0
- package/build/types/index.d.ts.map +1 -0
- package/build/types/index.js +2 -0
- package/build/types/index.js.map +1 -0
- package/build/utils/docs-downloader.d.ts +9 -0
- package/build/utils/docs-downloader.d.ts.map +1 -0
- package/build/utils/docs-downloader.js +82 -0
- package/build/utils/docs-downloader.js.map +1 -0
- package/build/utils/paths.d.ts +67 -0
- package/build/utils/paths.d.ts.map +1 -0
- package/build/utils/paths.js +132 -0
- package/build/utils/paths.js.map +1 -0
- package/build/utils/text-processing.d.ts +62 -0
- package/build/utils/text-processing.d.ts.map +1 -0
- package/build/utils/text-processing.js +214 -0
- package/build/utils/text-processing.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { mkdir } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { exec } from 'child_process';
|
|
5
|
+
import { promisify } from 'util';
|
|
6
|
+
const execAsync = promisify(exec);
|
|
7
|
+
/**
|
|
8
|
+
* Repository configuration
|
|
9
|
+
*/
|
|
10
|
+
const DOCS_REPO = 'https://github.com/SAP-docs/btp-cloud-platform.git';
|
|
11
|
+
/**
|
|
12
|
+
* Checks if documentation exists and downloads it if necessary
|
|
13
|
+
*/
|
|
14
|
+
export async function ensureDocsAvailable(docsPath) {
|
|
15
|
+
// Check if docs directory exists and has content
|
|
16
|
+
if (existsSync(docsPath)) {
|
|
17
|
+
const iSuitePath = join(docsPath, 'ISuite');
|
|
18
|
+
const ciPath = join(docsPath, 'ci');
|
|
19
|
+
const apimPath = join(docsPath, 'apim');
|
|
20
|
+
if (existsSync(iSuitePath) && existsSync(ciPath) && existsSync(apimPath)) {
|
|
21
|
+
console.error('Documentation found at:', docsPath);
|
|
22
|
+
return true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Docs not found - download from GitHub
|
|
26
|
+
console.error('\nDocumentation not found. Downloading from GitHub...');
|
|
27
|
+
console.error('This is a one-time operation and may take 1-2 minutes.\n');
|
|
28
|
+
try {
|
|
29
|
+
await downloadDocs(docsPath);
|
|
30
|
+
console.error('\n✓ Documentation downloaded successfully!\n');
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.error('\n✗ Failed to download documentation:', error);
|
|
35
|
+
console.error('\nPlease manually clone the official SAP documentation repository:');
|
|
36
|
+
console.error(` git clone ${DOCS_REPO}`);
|
|
37
|
+
console.error(` export MCP_DOCS_PATH=/path/to/btp-integration-suite/docs`);
|
|
38
|
+
console.error('\nThen restart the MCP server.');
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Downloads documentation from GitHub
|
|
44
|
+
*/
|
|
45
|
+
async function downloadDocs(docsPath) {
|
|
46
|
+
const parentDir = join(docsPath, '..');
|
|
47
|
+
// Create parent directory if it doesn't exist
|
|
48
|
+
await mkdir(parentDir, { recursive: true });
|
|
49
|
+
console.error('Cloning SAP Business Technology Platform documentation...');
|
|
50
|
+
const repoDir = join(parentDir, '.docs-repo');
|
|
51
|
+
// Clean up any existing partial download
|
|
52
|
+
if (existsSync(repoDir)) {
|
|
53
|
+
await execAsync(`rm -rf "${repoDir}"`);
|
|
54
|
+
}
|
|
55
|
+
// Clone with sparse checkout for docs folder only
|
|
56
|
+
const commands = [
|
|
57
|
+
`git clone --filter=blob:none --sparse "${DOCS_REPO}" "${repoDir}"`,
|
|
58
|
+
`cd "${repoDir}" && git sparse-checkout set docs`,
|
|
59
|
+
`mv "${repoDir}/docs" "${docsPath}"`,
|
|
60
|
+
`rm -rf "${repoDir}"`
|
|
61
|
+
];
|
|
62
|
+
for (const cmd of commands) {
|
|
63
|
+
await execAsync(cmd);
|
|
64
|
+
}
|
|
65
|
+
console.error('Documentation download complete.');
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Gets the size of the docs directory in MB
|
|
69
|
+
*/
|
|
70
|
+
export async function getDocsSize(docsPath) {
|
|
71
|
+
if (!existsSync(docsPath)) {
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const { stdout } = await execAsync(`du -sm "${docsPath}" | cut -f1`);
|
|
76
|
+
return parseInt(stdout.trim(), 10);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=docs-downloader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docs-downloader.js","sourceRoot":"","sources":["../../src/utils/docs-downloader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { DocumentArea } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the docs directory path.
|
|
4
|
+
* Tries environment variable first, then auto-detects from package location.
|
|
5
|
+
* Note: This returns a path even if it doesn't exist yet - existence check happens later.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveDocsPath(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Resolves cache directory path.
|
|
10
|
+
*/
|
|
11
|
+
export declare function resolveCacheDir(): string;
|
|
12
|
+
/**
|
|
13
|
+
* Normalizes a file path (removes trailing slashes, normalizes separators)
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizePath(path: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Resolves a relative link from a source file to an absolute path.
|
|
18
|
+
*
|
|
19
|
+
* @param sourcePath - Absolute path of the source file containing the link
|
|
20
|
+
* @param linkHref - The href from the markdown link
|
|
21
|
+
* @returns Absolute path to the linked file
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolveRelativeLink(sourcePath: string, linkHref: string): string;
|
|
24
|
+
/**
|
|
25
|
+
* Checks if a link is external (http://, https://, etc.)
|
|
26
|
+
*/
|
|
27
|
+
export declare function isExternalLink(href: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Extracts the document area from a file path.
|
|
30
|
+
*
|
|
31
|
+
* @param filePath - Absolute or relative file path
|
|
32
|
+
* @returns The document area (ISuite, ci, or apim)
|
|
33
|
+
*/
|
|
34
|
+
export declare function getDocumentArea(filePath: string): DocumentArea;
|
|
35
|
+
/**
|
|
36
|
+
* Converts an absolute path to a path relative to the docs directory.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getRelativePath(absolutePath: string, docsPath: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Converts a relative path (from docs directory) to an absolute path.
|
|
41
|
+
*/
|
|
42
|
+
export declare function getAbsolutePath(relativePath: string, docsPath: string): string;
|
|
43
|
+
/**
|
|
44
|
+
* Gets the area-specific directory path.
|
|
45
|
+
*
|
|
46
|
+
* @param area - The document area
|
|
47
|
+
* @param docsPath - Base docs directory path
|
|
48
|
+
* @returns Absolute path to the area directory
|
|
49
|
+
*/
|
|
50
|
+
export declare function getAreaPath(area: DocumentArea, docsPath: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Gets the index.md file path for a specific area.
|
|
53
|
+
*/
|
|
54
|
+
export declare function getIndexPath(area: DocumentArea, docsPath: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Checks if a file path belongs to a specific area.
|
|
57
|
+
*/
|
|
58
|
+
export declare function isInArea(filePath: string, area: DocumentArea): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Gets all area paths that should be searched.
|
|
61
|
+
*
|
|
62
|
+
* @param area - The area filter ('all' or specific area)
|
|
63
|
+
* @param docsPath - Base docs directory path
|
|
64
|
+
* @returns Array of area paths to search
|
|
65
|
+
*/
|
|
66
|
+
export declare function getAreaPaths(area: DocumentArea | 'all', docsPath: string): string[];
|
|
67
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAMtD;;;;GAIG;AACH,wBAAgB,eAAe,IAAI,MAAM,CASxC;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAahF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,CAa9D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAK9E;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAGtE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,YAAY,GAAG,KAAK,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAUnF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { fileURLToPath } from 'url';
|
|
2
|
+
import { dirname, join, relative, resolve, isAbsolute, normalize } from 'path';
|
|
3
|
+
// Get the directory of the current module
|
|
4
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
5
|
+
const __dirname = dirname(__filename);
|
|
6
|
+
/**
|
|
7
|
+
* Resolves the docs directory path.
|
|
8
|
+
* Tries environment variable first, then auto-detects from package location.
|
|
9
|
+
* Note: This returns a path even if it doesn't exist yet - existence check happens later.
|
|
10
|
+
*/
|
|
11
|
+
export function resolveDocsPath() {
|
|
12
|
+
// Check environment variable
|
|
13
|
+
if (process.env.MCP_DOCS_PATH) {
|
|
14
|
+
return resolve(process.env.MCP_DOCS_PATH);
|
|
15
|
+
}
|
|
16
|
+
// Auto-detect: go up from build/utils/ to package root, then to docs/
|
|
17
|
+
const projectRoot = resolve(__dirname, '..', '..');
|
|
18
|
+
return join(projectRoot, 'docs');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Resolves cache directory path.
|
|
22
|
+
*/
|
|
23
|
+
export function resolveCacheDir() {
|
|
24
|
+
const cacheDir = process.env.MCP_CACHE_DIR || '.mcp-cache';
|
|
25
|
+
return resolve(cacheDir);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Normalizes a file path (removes trailing slashes, normalizes separators)
|
|
29
|
+
*/
|
|
30
|
+
export function normalizePath(path) {
|
|
31
|
+
return normalize(path).replace(/[/\\]+$/, '');
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Resolves a relative link from a source file to an absolute path.
|
|
35
|
+
*
|
|
36
|
+
* @param sourcePath - Absolute path of the source file containing the link
|
|
37
|
+
* @param linkHref - The href from the markdown link
|
|
38
|
+
* @returns Absolute path to the linked file
|
|
39
|
+
*/
|
|
40
|
+
export function resolveRelativeLink(sourcePath, linkHref) {
|
|
41
|
+
// Remove anchor if present
|
|
42
|
+
const [pathPart] = linkHref.split('#');
|
|
43
|
+
if (!pathPart) {
|
|
44
|
+
// Just an anchor (same page)
|
|
45
|
+
return sourcePath;
|
|
46
|
+
}
|
|
47
|
+
const sourceDir = dirname(sourcePath);
|
|
48
|
+
const resolved = resolve(sourceDir, pathPart);
|
|
49
|
+
return normalizePath(resolved);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Checks if a link is external (http://, https://, etc.)
|
|
53
|
+
*/
|
|
54
|
+
export function isExternalLink(href) {
|
|
55
|
+
return /^(https?|ftp|mailto):/.test(href);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Extracts the document area from a file path.
|
|
59
|
+
*
|
|
60
|
+
* @param filePath - Absolute or relative file path
|
|
61
|
+
* @returns The document area (ISuite, ci, or apim)
|
|
62
|
+
*/
|
|
63
|
+
export function getDocumentArea(filePath) {
|
|
64
|
+
const normalized = normalizePath(filePath);
|
|
65
|
+
if (normalized.includes('/ISuite/') || normalized.includes('\\ISuite\\')) {
|
|
66
|
+
return 'ISuite';
|
|
67
|
+
}
|
|
68
|
+
else if (normalized.includes('/ci/') || normalized.includes('\\ci\\')) {
|
|
69
|
+
return 'ci';
|
|
70
|
+
}
|
|
71
|
+
else if (normalized.includes('/apim/') || normalized.includes('\\apim\\')) {
|
|
72
|
+
return 'apim';
|
|
73
|
+
}
|
|
74
|
+
// Default to ISuite if can't determine
|
|
75
|
+
return 'ISuite';
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Converts an absolute path to a path relative to the docs directory.
|
|
79
|
+
*/
|
|
80
|
+
export function getRelativePath(absolutePath, docsPath) {
|
|
81
|
+
return relative(docsPath, absolutePath);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Converts a relative path (from docs directory) to an absolute path.
|
|
85
|
+
*/
|
|
86
|
+
export function getAbsolutePath(relativePath, docsPath) {
|
|
87
|
+
if (isAbsolute(relativePath)) {
|
|
88
|
+
return relativePath;
|
|
89
|
+
}
|
|
90
|
+
return join(docsPath, relativePath);
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Gets the area-specific directory path.
|
|
94
|
+
*
|
|
95
|
+
* @param area - The document area
|
|
96
|
+
* @param docsPath - Base docs directory path
|
|
97
|
+
* @returns Absolute path to the area directory
|
|
98
|
+
*/
|
|
99
|
+
export function getAreaPath(area, docsPath) {
|
|
100
|
+
return join(docsPath, area);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Gets the index.md file path for a specific area.
|
|
104
|
+
*/
|
|
105
|
+
export function getIndexPath(area, docsPath) {
|
|
106
|
+
return join(docsPath, area, 'index.md');
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Checks if a file path belongs to a specific area.
|
|
110
|
+
*/
|
|
111
|
+
export function isInArea(filePath, area) {
|
|
112
|
+
const documentArea = getDocumentArea(filePath);
|
|
113
|
+
return documentArea === area;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Gets all area paths that should be searched.
|
|
117
|
+
*
|
|
118
|
+
* @param area - The area filter ('all' or specific area)
|
|
119
|
+
* @param docsPath - Base docs directory path
|
|
120
|
+
* @returns Array of area paths to search
|
|
121
|
+
*/
|
|
122
|
+
export function getAreaPaths(area, docsPath) {
|
|
123
|
+
if (area === 'all') {
|
|
124
|
+
return [
|
|
125
|
+
join(docsPath, 'ISuite'),
|
|
126
|
+
join(docsPath, 'ci'),
|
|
127
|
+
join(docsPath, 'apim'),
|
|
128
|
+
];
|
|
129
|
+
}
|
|
130
|
+
return [join(docsPath, area)];
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/utils/paths.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import type { TextChunk } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Normalizes text for searching (lowercase, trim, normalize whitespace)
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeText(text: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Tokenizes text into words
|
|
8
|
+
*/
|
|
9
|
+
export declare function tokenize(text: string): string[];
|
|
10
|
+
/**
|
|
11
|
+
* Extracts a snippet of text around a query match
|
|
12
|
+
*
|
|
13
|
+
* @param content - The full text content
|
|
14
|
+
* @param query - The search query
|
|
15
|
+
* @param contextLength - Number of characters to include before and after match
|
|
16
|
+
* @returns A snippet with the query highlighted in context
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractSnippet(content: string, query: string, contextLength?: number): string;
|
|
19
|
+
/**
|
|
20
|
+
* Calculates Levenshtein distance between two strings (for fuzzy matching)
|
|
21
|
+
*/
|
|
22
|
+
export declare function levenshteinDistance(a: string, b: string): number;
|
|
23
|
+
/**
|
|
24
|
+
* Calculates fuzzy match score (0-100) based on Levenshtein distance
|
|
25
|
+
* 100 = exact match, lower scores = more different
|
|
26
|
+
*/
|
|
27
|
+
export declare function fuzzyMatchScore(str1: string, str2: string): number;
|
|
28
|
+
/**
|
|
29
|
+
* Checks if text contains all words from query
|
|
30
|
+
*/
|
|
31
|
+
export declare function containsAllWords(text: string, query: string): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Counts how many query words appear in the text
|
|
34
|
+
*/
|
|
35
|
+
export declare function countMatchingWords(text: string, query: string): number;
|
|
36
|
+
/**
|
|
37
|
+
* Chunks text into smaller pieces with overlap
|
|
38
|
+
*
|
|
39
|
+
* @param text - The text to chunk
|
|
40
|
+
* @param maxTokens - Maximum tokens per chunk (approximate, using word count)
|
|
41
|
+
* @param overlapTokens - Number of tokens to overlap between chunks
|
|
42
|
+
* @returns Array of text chunks with metadata
|
|
43
|
+
*/
|
|
44
|
+
export declare function chunkText(text: string, maxTokens?: number, overlapTokens?: number): TextChunk[];
|
|
45
|
+
/**
|
|
46
|
+
* Strips markdown from text (basic implementation)
|
|
47
|
+
* For more robust stripping, use remark-strip-markdown
|
|
48
|
+
*/
|
|
49
|
+
export declare function stripMarkdownBasic(text: string): string;
|
|
50
|
+
/**
|
|
51
|
+
* Truncates text to a maximum length, breaking at word boundaries
|
|
52
|
+
*/
|
|
53
|
+
export declare function truncateText(text: string, maxLength: number): string;
|
|
54
|
+
/**
|
|
55
|
+
* Creates a hash from a string (simple implementation for cache keys)
|
|
56
|
+
*/
|
|
57
|
+
export declare function hashString(str: string): string;
|
|
58
|
+
/**
|
|
59
|
+
* Calculates cosine similarity between two vectors
|
|
60
|
+
*/
|
|
61
|
+
export declare function cosineSimilarity(a: number[], b: number[]): number;
|
|
62
|
+
//# sourceMappingURL=text-processing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-processing.d.ts","sourceRoot":"","sources":["../../src/utils/text-processing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAE/C;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,GAAE,MAAY,GAAG,MAAM,CA2BlG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CA6BhE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAiBlE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAKrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAKtE;AAED;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,GAAE,MAAY,EAAE,aAAa,GAAE,MAAW,GAAG,SAAS,EAAE,CA4BxG;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAwBvD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAapE;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAQ9C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,CAuBjE"}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalizes text for searching (lowercase, trim, normalize whitespace)
|
|
3
|
+
*/
|
|
4
|
+
export function normalizeText(text) {
|
|
5
|
+
return text.toLowerCase().trim().replace(/\s+/g, ' ');
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Tokenizes text into words
|
|
9
|
+
*/
|
|
10
|
+
export function tokenize(text) {
|
|
11
|
+
return normalizeText(text).split(/\s+/).filter(word => word.length > 0);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Extracts a snippet of text around a query match
|
|
15
|
+
*
|
|
16
|
+
* @param content - The full text content
|
|
17
|
+
* @param query - The search query
|
|
18
|
+
* @param contextLength - Number of characters to include before and after match
|
|
19
|
+
* @returns A snippet with the query highlighted in context
|
|
20
|
+
*/
|
|
21
|
+
export function extractSnippet(content, query, contextLength = 100) {
|
|
22
|
+
const normalizedContent = content.toLowerCase();
|
|
23
|
+
const normalizedQuery = query.toLowerCase();
|
|
24
|
+
// Find the first occurrence of the query
|
|
25
|
+
const index = normalizedContent.indexOf(normalizedQuery);
|
|
26
|
+
if (index === -1) {
|
|
27
|
+
// Query not found, return beginning of content
|
|
28
|
+
return content.substring(0, contextLength * 2) + (content.length > contextLength * 2 ? '...' : '');
|
|
29
|
+
}
|
|
30
|
+
// Calculate snippet boundaries
|
|
31
|
+
const start = Math.max(0, index - contextLength);
|
|
32
|
+
const end = Math.min(content.length, index + query.length + contextLength);
|
|
33
|
+
let snippet = content.substring(start, end);
|
|
34
|
+
// Add ellipsis if needed
|
|
35
|
+
if (start > 0) {
|
|
36
|
+
snippet = '...' + snippet;
|
|
37
|
+
}
|
|
38
|
+
if (end < content.length) {
|
|
39
|
+
snippet = snippet + '...';
|
|
40
|
+
}
|
|
41
|
+
return snippet.trim();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Calculates Levenshtein distance between two strings (for fuzzy matching)
|
|
45
|
+
*/
|
|
46
|
+
export function levenshteinDistance(a, b) {
|
|
47
|
+
const matrix = [];
|
|
48
|
+
// Initialize first column
|
|
49
|
+
for (let i = 0; i <= b.length; i++) {
|
|
50
|
+
matrix[i] = [i];
|
|
51
|
+
}
|
|
52
|
+
// Initialize first row
|
|
53
|
+
for (let j = 0; j <= a.length; j++) {
|
|
54
|
+
matrix[0][j] = j;
|
|
55
|
+
}
|
|
56
|
+
// Fill the matrix
|
|
57
|
+
for (let i = 1; i <= b.length; i++) {
|
|
58
|
+
for (let j = 1; j <= a.length; j++) {
|
|
59
|
+
if (b.charAt(i - 1) === a.charAt(j - 1)) {
|
|
60
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
|
|
64
|
+
matrix[i][j - 1] + 1, // insertion
|
|
65
|
+
matrix[i - 1][j] + 1 // deletion
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return matrix[b.length][a.length];
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Calculates fuzzy match score (0-100) based on Levenshtein distance
|
|
74
|
+
* 100 = exact match, lower scores = more different
|
|
75
|
+
*/
|
|
76
|
+
export function fuzzyMatchScore(str1, str2) {
|
|
77
|
+
const normalized1 = normalizeText(str1);
|
|
78
|
+
const normalized2 = normalizeText(str2);
|
|
79
|
+
if (normalized1 === normalized2) {
|
|
80
|
+
return 100;
|
|
81
|
+
}
|
|
82
|
+
const maxLen = Math.max(normalized1.length, normalized2.length);
|
|
83
|
+
if (maxLen === 0) {
|
|
84
|
+
return 100;
|
|
85
|
+
}
|
|
86
|
+
const distance = levenshteinDistance(normalized1, normalized2);
|
|
87
|
+
const score = Math.max(0, 100 - (distance / maxLen) * 100);
|
|
88
|
+
return Math.round(score);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Checks if text contains all words from query
|
|
92
|
+
*/
|
|
93
|
+
export function containsAllWords(text, query) {
|
|
94
|
+
const textWords = new Set(tokenize(text));
|
|
95
|
+
const queryWords = tokenize(query);
|
|
96
|
+
return queryWords.every(word => textWords.has(word));
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Counts how many query words appear in the text
|
|
100
|
+
*/
|
|
101
|
+
export function countMatchingWords(text, query) {
|
|
102
|
+
const textWords = new Set(tokenize(text));
|
|
103
|
+
const queryWords = tokenize(query);
|
|
104
|
+
return queryWords.filter(word => textWords.has(word)).length;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Chunks text into smaller pieces with overlap
|
|
108
|
+
*
|
|
109
|
+
* @param text - The text to chunk
|
|
110
|
+
* @param maxTokens - Maximum tokens per chunk (approximate, using word count)
|
|
111
|
+
* @param overlapTokens - Number of tokens to overlap between chunks
|
|
112
|
+
* @returns Array of text chunks with metadata
|
|
113
|
+
*/
|
|
114
|
+
export function chunkText(text, maxTokens = 500, overlapTokens = 50) {
|
|
115
|
+
const words = text.split(/\s+/);
|
|
116
|
+
const chunks = [];
|
|
117
|
+
let chunkIndex = 0;
|
|
118
|
+
let currentPosition = 0;
|
|
119
|
+
while (currentPosition < words.length) {
|
|
120
|
+
const chunkWords = words.slice(currentPosition, currentPosition + maxTokens);
|
|
121
|
+
const chunkText = chunkWords.join(' ');
|
|
122
|
+
chunks.push({
|
|
123
|
+
text: chunkText,
|
|
124
|
+
chunkIndex,
|
|
125
|
+
startOffset: currentPosition,
|
|
126
|
+
endOffset: currentPosition + chunkWords.length,
|
|
127
|
+
});
|
|
128
|
+
chunkIndex++;
|
|
129
|
+
currentPosition += maxTokens - overlapTokens;
|
|
130
|
+
// Prevent infinite loop
|
|
131
|
+
if (chunkWords.length === 0) {
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return chunks;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Strips markdown from text (basic implementation)
|
|
139
|
+
* For more robust stripping, use remark-strip-markdown
|
|
140
|
+
*/
|
|
141
|
+
export function stripMarkdownBasic(text) {
|
|
142
|
+
return text
|
|
143
|
+
// Remove HTML comments
|
|
144
|
+
.replace(/<!--[\s\S]*?-->/g, '')
|
|
145
|
+
// Remove code blocks
|
|
146
|
+
.replace(/```[\s\S]*?```/g, '')
|
|
147
|
+
// Remove inline code
|
|
148
|
+
.replace(/`[^`]+`/g, '')
|
|
149
|
+
// Remove images
|
|
150
|
+
.replace(/!\[.*?\]\(.*?\)/g, '')
|
|
151
|
+
// Remove links but keep text
|
|
152
|
+
.replace(/\[([^\]]+)\]\([^\)]+\)/g, '$1')
|
|
153
|
+
// Remove headers
|
|
154
|
+
.replace(/^#+\s+/gm, '')
|
|
155
|
+
// Remove bold/italic
|
|
156
|
+
.replace(/\*\*([^*]+)\*\*/g, '$1')
|
|
157
|
+
.replace(/\*([^*]+)\*/g, '$1')
|
|
158
|
+
.replace(/__([^_]+)__/g, '$1')
|
|
159
|
+
.replace(/_([^_]+)_/g, '$1')
|
|
160
|
+
// Remove blockquotes
|
|
161
|
+
.replace(/^>\s+/gm, '')
|
|
162
|
+
// Normalize whitespace
|
|
163
|
+
.replace(/\n\n+/g, '\n\n')
|
|
164
|
+
.trim();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Truncates text to a maximum length, breaking at word boundaries
|
|
168
|
+
*/
|
|
169
|
+
export function truncateText(text, maxLength) {
|
|
170
|
+
if (text.length <= maxLength) {
|
|
171
|
+
return text;
|
|
172
|
+
}
|
|
173
|
+
const truncated = text.substring(0, maxLength);
|
|
174
|
+
const lastSpace = truncated.lastIndexOf(' ');
|
|
175
|
+
if (lastSpace > 0) {
|
|
176
|
+
return truncated.substring(0, lastSpace) + '...';
|
|
177
|
+
}
|
|
178
|
+
return truncated + '...';
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Creates a hash from a string (simple implementation for cache keys)
|
|
182
|
+
*/
|
|
183
|
+
export function hashString(str) {
|
|
184
|
+
let hash = 0;
|
|
185
|
+
for (let i = 0; i < str.length; i++) {
|
|
186
|
+
const char = str.charCodeAt(i);
|
|
187
|
+
hash = ((hash << 5) - hash) + char;
|
|
188
|
+
hash = hash & hash; // Convert to 32-bit integer
|
|
189
|
+
}
|
|
190
|
+
return Math.abs(hash).toString(36);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Calculates cosine similarity between two vectors
|
|
194
|
+
*/
|
|
195
|
+
export function cosineSimilarity(a, b) {
|
|
196
|
+
if (a.length !== b.length) {
|
|
197
|
+
throw new Error('Vectors must have the same length');
|
|
198
|
+
}
|
|
199
|
+
let dotProduct = 0;
|
|
200
|
+
let normA = 0;
|
|
201
|
+
let normB = 0;
|
|
202
|
+
for (let i = 0; i < a.length; i++) {
|
|
203
|
+
dotProduct += a[i] * b[i];
|
|
204
|
+
normA += a[i] * a[i];
|
|
205
|
+
normB += b[i] * b[i];
|
|
206
|
+
}
|
|
207
|
+
normA = Math.sqrt(normA);
|
|
208
|
+
normB = Math.sqrt(normB);
|
|
209
|
+
if (normA === 0 || normB === 0) {
|
|
210
|
+
return 0;
|
|
211
|
+
}
|
|
212
|
+
return dotProduct / (normA * normB);
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=text-processing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-processing.js","sourceRoot":"","sources":["../../src/utils/text-processing.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@contiva/sapbtp-docs-mcp",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "MCP server for SAP Business Technology Platform documentation - enables AI assistants to search and navigate SAP Business Technology Platform docs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./build/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"sapbtp-docs-mcp": "build/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"prepare": "npm run build",
|
|
13
|
+
"dev": "tsc --watch",
|
|
14
|
+
"start": "node ./build/index.js",
|
|
15
|
+
"prepublishOnly": "npm run build"
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"build/**/*",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"mcp",
|
|
24
|
+
"sap",
|
|
25
|
+
"business-technology-platform",
|
|
26
|
+
"documentation",
|
|
27
|
+
"search",
|
|
28
|
+
"ai",
|
|
29
|
+
"claude"
|
|
30
|
+
],
|
|
31
|
+
"author": "Robert Fels",
|
|
32
|
+
"license": "Apache-2.0",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/robertfels/sapbtp-docs-mcp.git"
|
|
36
|
+
},
|
|
37
|
+
"homepage": "https://github.com/robertfels/sapbtp-docs-mcp#readme",
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/robertfels/sapbtp-docs-mcp/issues"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@modelcontextprotocol/sdk": "^1.0.4",
|
|
43
|
+
"@xenova/transformers": "^2.17.2",
|
|
44
|
+
"gray-matter": "^4.0.3",
|
|
45
|
+
"remark": "^15.0.1",
|
|
46
|
+
"remark-gfm": "^4.0.0",
|
|
47
|
+
"strip-markdown": "^6.0.0"
|
|
48
|
+
},
|
|
49
|
+
"optionalDependencies": {
|
|
50
|
+
"voyageai": "^0.0.6",
|
|
51
|
+
"openai": "^4.77.0"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@types/node": "^22.10.2",
|
|
55
|
+
"typescript": "^5.7.2"
|
|
56
|
+
},
|
|
57
|
+
"engines": {
|
|
58
|
+
"node": ">=18.0.0"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public"
|
|
62
|
+
}
|
|
63
|
+
}
|