@convertcom/mcp-server 0.0.1-beta.5 → 0.0.1-beta.7
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/build/api-config.d.ts +1 -1
- package/build/api-config.js +10 -16
- package/build/api-config.js.map +1 -1
- package/build/executor.d.ts +0 -1
- package/build/executor.js +33 -11
- package/build/executor.js.map +1 -1
- package/build/index.d.ts +0 -8
- package/build/index.js +96 -45
- package/build/index.js.map +1 -1
- package/build/kb-hybrid.d.ts +20 -0
- package/build/kb-hybrid.js +69 -0
- package/build/kb-hybrid.js.map +1 -0
- package/build/kb-semantic.d.ts +16 -0
- package/build/kb-semantic.js +97 -0
- package/build/kb-semantic.js.map +1 -0
- package/build/namespaced.d.ts +6 -0
- package/build/namespaced.js +295 -29
- package/build/namespaced.js.map +1 -1
- package/build/tools.js +527 -816
- package/build/tools.js.map +1 -1
- package/package.json +27 -25
package/build/api-config.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export declare const API_BASE_URL: string;
|
package/build/api-config.js
CHANGED
|
@@ -1,35 +1,29 @@
|
|
|
1
1
|
import axios from 'axios';
|
|
2
2
|
import crypto from 'crypto';
|
|
3
|
+
export const API_BASE_URL = process.env.API_BASE_URL || 'https://api.convert.com/api/v2';
|
|
3
4
|
axios.defaults.headers.post['Content-Type'] = 'application/json';
|
|
4
5
|
axios.defaults.headers.put['Content-Type'] = 'application/json';
|
|
5
|
-
//axios.defaults.headers.get['Content-Type'] = 'application/json';
|
|
6
6
|
axios.defaults.transformRequest = [
|
|
7
7
|
function (data, headers) {
|
|
8
|
-
//console.warn('data', data);
|
|
9
8
|
if (!data) {
|
|
10
9
|
data = {};
|
|
11
10
|
}
|
|
12
11
|
return JSON.stringify(data);
|
|
13
12
|
},
|
|
14
13
|
];
|
|
15
|
-
// Add a request interceptor to set the 'x-convert-nonce' header
|
|
16
14
|
axios.interceptors.request.use((config) => {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
let signString = applicationID + '\n' + expiresTimestamp + '\n' + requestURL + '\n' + requestBody;
|
|
27
|
-
let hash = crypto.createHmac('sha256', applicationSecretKey).update(signString).digest('hex');
|
|
28
|
-
let authorization = 'Convert-HMAC-SHA256 Signature=' + hash;
|
|
15
|
+
const applicationID = process.env.CONVERT_API_KEY;
|
|
16
|
+
const applicationSecretKey = process.env.CONVERT_API_SECRET;
|
|
17
|
+
const expires = 60;
|
|
18
|
+
const requestURL = config.url;
|
|
19
|
+
const requestBody = config.data ? JSON.stringify(config.data) : '{}';
|
|
20
|
+
const expiresTimestamp = Date.now() / 1000 + expires;
|
|
21
|
+
const signString = applicationID + '\n' + expiresTimestamp + '\n' + requestURL + '\n' + requestBody;
|
|
22
|
+
const hash = crypto.createHmac('sha256', applicationSecretKey).update(signString).digest('hex');
|
|
23
|
+
const authorization = 'Convert-HMAC-SHA256 Signature=' + hash;
|
|
29
24
|
config.headers['Convert-Application-ID'] = applicationID;
|
|
30
25
|
config.headers['Expires'] = expiresTimestamp;
|
|
31
26
|
config.headers['Authorization'] = authorization;
|
|
32
|
-
// console.warn('config.headers:', config.headers);
|
|
33
27
|
return config;
|
|
34
28
|
}, (error) => {
|
|
35
29
|
return Promise.reject(error);
|
package/build/api-config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-config.js","sourceRoot":"","sources":["../src/api-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;AACjE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;AAChE,
|
|
1
|
+
{"version":3,"file":"api-config.js","sourceRoot":"","sources":["../src/api-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,MAAM,CAAC,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,gCAAgC,CAAC;AAEzF,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;AACjE,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,kBAAkB,CAAC;AAChE,KAAK,CAAC,QAAQ,CAAC,gBAAgB,GAAG;IAChC,UAAU,IAAS,EAAE,OAAY;QAC/B,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;CACF,CAAC;AAEF,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,CAC5B,CAAC,MAAM,EAAE,EAAE;IACT,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAClD,MAAM,oBAAoB,GAAG,OAAO,CAAC,GAAG,CAAC,kBAA4B,CAAC;IACtE,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,MAAM,UAAU,GAAG,MAAM,CAAC,GAAG,CAAC;IAC9B,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACrE,MAAM,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC;IAErD,MAAM,UAAU,GACd,aAAa,GAAG,IAAI,GAAG,gBAAgB,GAAG,IAAI,GAAG,UAAU,GAAG,IAAI,GAAG,WAAW,CAAC;IAEnF,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,oBAAoB,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAChG,MAAM,aAAa,GAAG,gCAAgC,GAAG,IAAI,CAAC;IAE9D,MAAM,CAAC,OAAO,CAAC,wBAAwB,CAAC,GAAG,aAAa,CAAC;IACzD,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,gBAAgB,CAAC;IAC7C,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,aAAa,CAAC;IAEhD,OAAO,MAAM,CAAC;AAChB,CAAC,EACD,CAAC,KAAK,EAAE,EAAE;IACR,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC/B,CAAC,CACF,CAAC"}
|
package/build/executor.d.ts
CHANGED
package/build/executor.js
CHANGED
|
@@ -2,11 +2,15 @@ import { z, ZodError } from 'zod';
|
|
|
2
2
|
import { jsonSchemaToZod } from 'json-schema-to-zod';
|
|
3
3
|
import axios from 'axios';
|
|
4
4
|
import { toolDefinitionMap } from './tools.js';
|
|
5
|
-
import './api-config.js';
|
|
5
|
+
import { API_BASE_URL } from './api-config.js';
|
|
6
6
|
export async function executeToolByName(toolName, toolArgs) {
|
|
7
7
|
const toolDefinition = toolDefinitionMap.get(toolName);
|
|
8
8
|
if (!toolDefinition) {
|
|
9
|
-
return {
|
|
9
|
+
return {
|
|
10
|
+
isError: true,
|
|
11
|
+
content: [{ type: 'text', text: 'Error: Unknown tool requested: ' + toolName }],
|
|
12
|
+
structuredContent: { error: `Unknown tool: ${toolName}` },
|
|
13
|
+
};
|
|
10
14
|
}
|
|
11
15
|
return await executeApiTool(toolName, toolDefinition, toolArgs);
|
|
12
16
|
}
|
|
@@ -20,12 +24,20 @@ async function executeApiTool(toolName, definition, toolArgs) {
|
|
|
20
24
|
}
|
|
21
25
|
catch (error) {
|
|
22
26
|
if (error instanceof ZodError) {
|
|
23
|
-
const validationErrorMessage = 'Invalid arguments. Common issue: Array parameters (like "include", "expand") must be passed as arrays, even for single values. Example: {"query": {"include": ["goals"]}} not {"query": {"include": "goals"}}. Details: ' + JSON.stringify(error.
|
|
24
|
-
return {
|
|
27
|
+
const validationErrorMessage = 'Invalid arguments. Common issue: Array parameters (like "include", "expand") must be passed as arrays, even for single values. Example: {"query": {"include": ["goals"]}} not {"query": {"include": "goals"}}. Details: ' + JSON.stringify(error.issues, null, 2);
|
|
28
|
+
return {
|
|
29
|
+
isError: true,
|
|
30
|
+
content: [{ type: 'text', text: validationErrorMessage }],
|
|
31
|
+
structuredContent: { error: 'Invalid arguments', issues: error.issues },
|
|
32
|
+
};
|
|
25
33
|
}
|
|
26
34
|
else {
|
|
27
35
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
28
|
-
return {
|
|
36
|
+
return {
|
|
37
|
+
isError: true,
|
|
38
|
+
content: [{ type: 'text', text: 'Internal error during validation setup: ' + errorMessage }],
|
|
39
|
+
structuredContent: { error: errorMessage },
|
|
40
|
+
};
|
|
29
41
|
}
|
|
30
42
|
}
|
|
31
43
|
let urlPath = definition.pathTemplate;
|
|
@@ -57,7 +69,7 @@ async function executeApiTool(toolName, definition, toolArgs) {
|
|
|
57
69
|
throw new Error(`Failed to resolve path parameters: ${urlPath}`);
|
|
58
70
|
}
|
|
59
71
|
// Build full URL with query string directly - don't rely on axios params serialization
|
|
60
|
-
let fullUrl =
|
|
72
|
+
let fullUrl = API_BASE_URL + urlPath;
|
|
61
73
|
if (Object.keys(queryParams).length > 0) {
|
|
62
74
|
// Serialize query params with bracket notation for arrays
|
|
63
75
|
const parts = [];
|
|
@@ -87,7 +99,8 @@ async function executeApiTool(toolName, definition, toolArgs) {
|
|
|
87
99
|
const response = await axios(config);
|
|
88
100
|
let responseText = '';
|
|
89
101
|
const contentType = response.headers['content-type']?.toLowerCase() || '';
|
|
90
|
-
|
|
102
|
+
const isJsonResponse = contentType.includes('application/json') && typeof response.data === 'object' && response.data !== null;
|
|
103
|
+
if (isJsonResponse) {
|
|
91
104
|
try {
|
|
92
105
|
responseText = JSON.stringify(response.data, null, 2);
|
|
93
106
|
}
|
|
@@ -104,7 +117,12 @@ async function executeApiTool(toolName, definition, toolArgs) {
|
|
|
104
117
|
else {
|
|
105
118
|
responseText = `(Status: ${response.status} - No body content)`;
|
|
106
119
|
}
|
|
107
|
-
return {
|
|
120
|
+
return {
|
|
121
|
+
content: [{ type: 'text', text: `API Response (Status: ${response.status}):\n${responseText}` }],
|
|
122
|
+
structuredContent: isJsonResponse
|
|
123
|
+
? { status: response.status, data: response.data }
|
|
124
|
+
: { status: response.status },
|
|
125
|
+
};
|
|
108
126
|
}
|
|
109
127
|
catch (error) {
|
|
110
128
|
let errorMessage;
|
|
@@ -118,7 +136,11 @@ async function executeApiTool(toolName, definition, toolArgs) {
|
|
|
118
136
|
errorMessage = `Unexpected error: ${String(error)}`;
|
|
119
137
|
}
|
|
120
138
|
console.error(`Error during execution: ${errorMessage}`);
|
|
121
|
-
return {
|
|
139
|
+
return {
|
|
140
|
+
isError: true,
|
|
141
|
+
content: [{ type: 'text', text: errorMessage }],
|
|
142
|
+
structuredContent: { error: errorMessage },
|
|
143
|
+
};
|
|
122
144
|
}
|
|
123
145
|
}
|
|
124
146
|
function formatApiError(error) {
|
|
@@ -159,9 +181,9 @@ function getZodSchemaFromJsonSchema(jsonSchema, toolName) {
|
|
|
159
181
|
}
|
|
160
182
|
try {
|
|
161
183
|
const zodSchemaString = jsonSchemaToZod(jsonSchema);
|
|
162
|
-
const zodSchema =
|
|
184
|
+
const zodSchema = new Function('z', 'return ' + zodSchemaString)(z);
|
|
163
185
|
if (typeof zodSchema?.parse !== 'function') {
|
|
164
|
-
throw new Error('
|
|
186
|
+
throw new Error('Schema evaluation did not produce a valid Zod schema.');
|
|
165
187
|
}
|
|
166
188
|
return zodSchema;
|
|
167
189
|
}
|
package/build/executor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAC;AAClC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAmD,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,iBAAiB,EAA0B,MAAM,YAAY,CAAC;AACvE,OAAO,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"executor.js","sourceRoot":"","sources":["../src/executor.ts"],"names":[],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -3,16 +3,8 @@
|
|
|
3
3
|
* MCP Server generated from OpenAPI spec for convert-api v2.0.0
|
|
4
4
|
* Generated on: 2025-06-05T16:52:41.275Z
|
|
5
5
|
*/
|
|
6
|
-
import './api-config.js';
|
|
7
6
|
/**
|
|
8
7
|
* Server configuration
|
|
9
8
|
*/
|
|
10
9
|
export declare const SERVER_NAME = "convert-api";
|
|
11
10
|
export declare const SERVER_VERSION = "2.0.0";
|
|
12
|
-
export declare const API_BASE_URL = "https://api.convert.com/api/v2";
|
|
13
|
-
/**
|
|
14
|
-
* Formats API errors for better readability
|
|
15
|
-
*
|
|
16
|
-
* @param error Axios error
|
|
17
|
-
* @returns Formatted error message
|
|
18
|
-
*/
|
package/build/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
// Load environment variables from .env file
|
|
7
7
|
import dotenv from 'dotenv';
|
|
8
|
-
dotenv.config();
|
|
8
|
+
dotenv.config({ quiet: true });
|
|
9
9
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
10
10
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
11
11
|
import { CallToolRequestSchema, ListToolsRequestSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
@@ -14,36 +14,44 @@ import { getNamespacedTools, executeNamespacedTool, isNamespace } from './namesp
|
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { resolve, dirname } from 'node:path';
|
|
16
16
|
import { KbSearchService } from './kb-search.js';
|
|
17
|
+
import { SemanticKbSearchService } from './kb-semantic.js';
|
|
18
|
+
import { HybridKbSearchService } from './kb-hybrid.js';
|
|
17
19
|
if (process.env.NODE_ENV === 'development') {
|
|
18
20
|
import('mcps-logger/console');
|
|
19
21
|
}
|
|
20
|
-
import './api-config.js';
|
|
22
|
+
import { API_BASE_URL } from './api-config.js';
|
|
21
23
|
import { toolDefinitionMap } from './tools.js';
|
|
22
24
|
import { DebugLogger } from './debug-log.js';
|
|
23
25
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
24
26
|
const knowledgeBasePath = resolve(__dirname, '..', 'data', 'convert-kb.json');
|
|
25
|
-
const
|
|
27
|
+
const vectorsDir = resolve(__dirname, '..', 'data', 'kb-vectors');
|
|
28
|
+
const keywordSearch = new KbSearchService(knowledgeBasePath);
|
|
29
|
+
const semanticSearch = new SemanticKbSearchService(knowledgeBasePath, vectorsDir);
|
|
30
|
+
const hybridSearch = new HybridKbSearchService(keywordSearch, semanticSearch);
|
|
26
31
|
const SERVER_INSTRUCTIONS = [
|
|
27
|
-
"You
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
|
|
32
|
+
"You have DIRECT API ACCESS to the user's Convert.com account.",
|
|
33
|
+
"This server provides 13 namespace tools (accounts, projects, domains, experiences, sections,",
|
|
34
|
+
"goals, tags, hypotheses, knowledgebases, observations, locations, audiences, features) that",
|
|
35
|
+
"call the Convert.com REST API on behalf of the authenticated user.",
|
|
36
|
+
"",
|
|
37
|
+
"WHEN THE USER ASKS ABOUT THEIR CONVERT DATA, USE THE NAMESPACE TOOLS DIRECTLY.",
|
|
38
|
+
"For example: 'what are my projects?' → call the 'projects' tool with action 'list'.",
|
|
39
|
+
"'show my A/B tests' → call the 'experiences' tool with action 'list'.",
|
|
40
|
+
"Each namespace tool accepts: { action, path, query, body }. Check _meta.available_actions for details.",
|
|
41
|
+
"",
|
|
42
|
+
"The 'search_knowledge_base' tool searches Convert's support documentation — use it when you need",
|
|
43
|
+
"help with Convert concepts, terminology, or setup guides. It does NOT access the user's account data.",
|
|
44
|
+
"",
|
|
45
|
+
"Key rules:",
|
|
46
|
+
"- Whenever an API response returns raw IDs (goals, projects, audiences, etc.), immediately enrich",
|
|
47
|
+
" those IDs by calling the appropriate namespace tool so the final answer contains descriptive names.",
|
|
48
|
+
" The human should never have to resolve IDs manually.",
|
|
49
|
+
"- When fetching resources with related data, ALWAYS use BOTH 'include' AND 'expand' query parameters",
|
|
50
|
+
" together: {\"query\": {\"include\": [\"goals\"], \"expand\": [\"goals\"]}}.",
|
|
51
|
+
" 'include' alone returns useless numeric IDs. 'expand' provides the full object data.",
|
|
52
|
+
"- Array parameters (include, expand) must always be arrays, even for single values.",
|
|
53
|
+
"- Pay attention to API response codes and any 'alerts' array in the payload."
|
|
54
|
+
].join('\n');
|
|
47
55
|
const debugLogger = new DebugLogger(process.env.CONVERT_DEBUG_LOG === '1' || process.env.CONVERT_DEBUG_LOG?.toLowerCase() === 'true');
|
|
48
56
|
function normalizeLooseJson(input) {
|
|
49
57
|
let output = input
|
|
@@ -100,18 +108,47 @@ function extractQueryArgument(rawArgs) {
|
|
|
100
108
|
return null;
|
|
101
109
|
}
|
|
102
110
|
const searchKnowledgeBaseTool = {
|
|
103
|
-
name: '
|
|
104
|
-
|
|
111
|
+
name: 'search_knowledge_base',
|
|
112
|
+
title: 'Search Knowledge Base',
|
|
113
|
+
description: 'Search Convert.com support documentation for product concepts, terminology, setup guides, and workflows. This does NOT access the user\'s account — use the namespace tools (projects, experiences, goals, etc.) to query live account data.',
|
|
105
114
|
inputSchema: {
|
|
106
115
|
type: 'object',
|
|
107
116
|
properties: {
|
|
108
117
|
query: {
|
|
109
118
|
type: 'string',
|
|
110
|
-
description: '
|
|
119
|
+
description: 'Search query — use specific terms like product names, feature labels, or integration names (e.g., "install convert on shopify", "goal types", "GDPR consent").'
|
|
111
120
|
}
|
|
112
121
|
},
|
|
113
122
|
required: ['query'],
|
|
114
123
|
additionalProperties: false
|
|
124
|
+
},
|
|
125
|
+
outputSchema: {
|
|
126
|
+
type: 'object',
|
|
127
|
+
properties: {
|
|
128
|
+
query: { type: 'string', description: 'The query that was searched.' },
|
|
129
|
+
results: {
|
|
130
|
+
type: 'array',
|
|
131
|
+
description: 'Matching knowledge base articles, ranked by relevance.',
|
|
132
|
+
items: {
|
|
133
|
+
type: 'object',
|
|
134
|
+
properties: {
|
|
135
|
+
title: { type: 'string', description: 'Article title.' },
|
|
136
|
+
url: { type: 'string', description: 'Source URL of the support article.' },
|
|
137
|
+
snippet: { type: 'string', description: 'Relevant excerpt from the article.' },
|
|
138
|
+
score: { type: 'number', description: 'Relevance score normalized 0–1 (1 = best match).' }
|
|
139
|
+
},
|
|
140
|
+
required: ['title', 'url', 'snippet', 'score']
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
},
|
|
144
|
+
required: ['query', 'results']
|
|
145
|
+
},
|
|
146
|
+
annotations: {
|
|
147
|
+
title: 'Search Knowledge Base',
|
|
148
|
+
readOnlyHint: true,
|
|
149
|
+
destructiveHint: false,
|
|
150
|
+
idempotentHint: true,
|
|
151
|
+
openWorldHint: false
|
|
115
152
|
}
|
|
116
153
|
};
|
|
117
154
|
function getToolsForClient() {
|
|
@@ -123,11 +160,15 @@ function getToolsForClient() {
|
|
|
123
160
|
*/
|
|
124
161
|
export const SERVER_NAME = "convert-api";
|
|
125
162
|
export const SERVER_VERSION = "2.0.0";
|
|
126
|
-
export const API_BASE_URL = "https://api.convert.com/api/v2";
|
|
127
163
|
/**
|
|
128
164
|
* MCP Server instance
|
|
129
165
|
*/
|
|
130
|
-
const server = new Server({
|
|
166
|
+
const server = new Server({
|
|
167
|
+
name: SERVER_NAME,
|
|
168
|
+
version: SERVER_VERSION,
|
|
169
|
+
title: 'Convert.com',
|
|
170
|
+
description: 'Direct API access to the user\'s Convert.com A/B testing account — manage experiences, projects, goals, audiences, and more. Includes a knowledge base for product documentation.',
|
|
171
|
+
}, {
|
|
131
172
|
capabilities: { tools: {} },
|
|
132
173
|
instructions: SERVER_INSTRUCTIONS
|
|
133
174
|
});
|
|
@@ -137,20 +178,20 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
|
137
178
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
138
179
|
const { name: toolName, arguments: toolArgs } = request.params;
|
|
139
180
|
debugLogger.log('callToolRequest', { toolName, arguments: toolArgs });
|
|
140
|
-
if (toolName === '
|
|
181
|
+
if (toolName === 'search_knowledge_base') {
|
|
141
182
|
try {
|
|
142
183
|
const query = extractQueryArgument(toolArgs);
|
|
143
184
|
if (!query) {
|
|
144
|
-
debugLogger.log('
|
|
185
|
+
debugLogger.log('search_knowledge_base.invalidArguments', { toolArgs });
|
|
145
186
|
return {
|
|
146
187
|
isError: true,
|
|
147
|
-
content: [{ type: 'text', text: "Error: The 'query' argument is required for
|
|
148
|
-
structuredContent: { error: "The 'query' argument is required for
|
|
188
|
+
content: [{ type: 'text', text: "Error: The 'query' argument is required for search_knowledge_base." }],
|
|
189
|
+
structuredContent: { error: "The 'query' argument is required for search_knowledge_base." }
|
|
149
190
|
};
|
|
150
191
|
}
|
|
151
|
-
const results =
|
|
192
|
+
const results = await hybridSearch.search(query, 5);
|
|
152
193
|
if (results.length === 0) {
|
|
153
|
-
debugLogger.log('
|
|
194
|
+
debugLogger.log('search_knowledge_base.noResults', { query });
|
|
154
195
|
return {
|
|
155
196
|
content: [{ type: 'text', text: `No knowledge base entries were found for the query: "${query}".` }],
|
|
156
197
|
structuredContent: { query, results: [], message: `No knowledge base entries found for "${query}".` }
|
|
@@ -169,7 +210,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
169
210
|
const scoreText = Number.isFinite(result.score) ? ` (Relevance: ${(result.score * 100).toFixed(1)}%)` : '';
|
|
170
211
|
return `${index + 1}. ${result.title}${scoreText}\n${result.url}\n${result.snippet}`;
|
|
171
212
|
}).join('\n\n---\n\n');
|
|
172
|
-
debugLogger.log('
|
|
213
|
+
debugLogger.log('search_knowledge_base.success', { query, matchCount: results.length });
|
|
173
214
|
return {
|
|
174
215
|
content: [{ type: 'text', text: textSummary }],
|
|
175
216
|
structuredContent: { query, results: structuredResults }
|
|
@@ -177,7 +218,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
177
218
|
}
|
|
178
219
|
catch (error) {
|
|
179
220
|
const message = error instanceof Error ? error.message : String(error);
|
|
180
|
-
debugLogger.log('
|
|
221
|
+
debugLogger.log('search_knowledge_base.error', { toolArgs, error: message });
|
|
181
222
|
return {
|
|
182
223
|
isError: true,
|
|
183
224
|
content: [{ type: 'text', text: `Unexpected error during knowledge base search: ${message}` }],
|
|
@@ -197,7 +238,11 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
197
238
|
}
|
|
198
239
|
console.error(`Error: Unknown tool requested: ${toolName}`);
|
|
199
240
|
debugLogger.log('unknownTool', { toolName });
|
|
200
|
-
return {
|
|
241
|
+
return {
|
|
242
|
+
isError: true,
|
|
243
|
+
content: [{ type: 'text', text: `Error: Unknown tool requested: ${toolName}` }],
|
|
244
|
+
structuredContent: { error: `Unknown tool: ${toolName}` },
|
|
245
|
+
};
|
|
201
246
|
});
|
|
202
247
|
/**
|
|
203
248
|
* Main function to start the server
|
|
@@ -219,7 +264,20 @@ async function main() {
|
|
|
219
264
|
*/
|
|
220
265
|
async function cleanup() {
|
|
221
266
|
console.error("Shutting down MCP server...");
|
|
222
|
-
|
|
267
|
+
await semanticSearch.waitReady().catch(() => { });
|
|
268
|
+
// Check BEFORE close() — close() clears references used by this check.
|
|
269
|
+
const loadedNativeRuntime = semanticSearch.hasNativeRuntimeLoaded();
|
|
270
|
+
hybridSearch.close();
|
|
271
|
+
// When both ONNX Runtime (HF Transformers) and Zvec native addons are
|
|
272
|
+
// loaded, their C++ atexit destructors conflict causing a libc++ abort.
|
|
273
|
+
// SIGKILL skips atexit entirely. The Zvec collection is read-only so
|
|
274
|
+
// skipping its close is safe (no write buffers to flush).
|
|
275
|
+
if (loadedNativeRuntime) {
|
|
276
|
+
process.kill(process.pid, 'SIGKILL');
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
process.exit(0);
|
|
280
|
+
}
|
|
223
281
|
}
|
|
224
282
|
// Register signal handlers
|
|
225
283
|
process.on('SIGINT', cleanup);
|
|
@@ -229,11 +287,4 @@ main().catch((error) => {
|
|
|
229
287
|
console.error("Fatal error in main execution:", error);
|
|
230
288
|
process.exit(1);
|
|
231
289
|
});
|
|
232
|
-
/**
|
|
233
|
-
* Formats API errors for better readability
|
|
234
|
-
*
|
|
235
|
-
* @param error Axios error
|
|
236
|
-
* @returns Formatted error message
|
|
237
|
-
*/
|
|
238
|
-
// Removed legacy per-tool executor from index; execution handled by executor.ts and namespaced.ts
|
|
239
290
|
//# sourceMappingURL=index.js.map
|
package/build/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,4CAA4C;AAC5C,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,MAAM,CAAC,MAAM,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { KbSearchService, SearchResult } from './kb-search.js';
|
|
2
|
+
import type { SemanticKbSearchService } from './kb-semantic.js';
|
|
3
|
+
export declare class HybridKbSearchService {
|
|
4
|
+
private readonly keyword;
|
|
5
|
+
private readonly semantic;
|
|
6
|
+
constructor(keyword: KbSearchService, semantic: SemanticKbSearchService);
|
|
7
|
+
search(query: string, limit?: number): Promise<SearchResult[]>;
|
|
8
|
+
close(): void;
|
|
9
|
+
/**
|
|
10
|
+
* Reciprocal Rank Fusion (RRF) — merges two ranked result lists.
|
|
11
|
+
*
|
|
12
|
+
* For each result at rank r (0-indexed):
|
|
13
|
+
* rrfScore(chunk) += 1 / (k + r + 1) where k = 60
|
|
14
|
+
*
|
|
15
|
+
* Deduplicates by chunk URL. When a chunk appears in both sets,
|
|
16
|
+
* keeps the keyword SearchResult (it has query-highlighted snippets).
|
|
17
|
+
* Normalizes final scores to 0–1 range.
|
|
18
|
+
*/
|
|
19
|
+
static fuseRRF(keyword: SearchResult[], semantic: SearchResult[], limit: number): SearchResult[];
|
|
20
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
const RRF_K = 60;
|
|
2
|
+
const OVERFETCH_FACTOR = 3;
|
|
3
|
+
export class HybridKbSearchService {
|
|
4
|
+
keyword;
|
|
5
|
+
semantic;
|
|
6
|
+
constructor(keyword, semantic) {
|
|
7
|
+
this.keyword = keyword;
|
|
8
|
+
this.semantic = semantic;
|
|
9
|
+
}
|
|
10
|
+
async search(query, limit = 5) {
|
|
11
|
+
if (!this.semantic.isReady()) {
|
|
12
|
+
return this.keyword.search(query, limit);
|
|
13
|
+
}
|
|
14
|
+
const fetchLimit = limit * OVERFETCH_FACTOR;
|
|
15
|
+
const [keywordResults, semanticResults] = await Promise.all([
|
|
16
|
+
Promise.resolve(this.keyword.search(query, fetchLimit)),
|
|
17
|
+
this.semantic.search(query, fetchLimit),
|
|
18
|
+
]);
|
|
19
|
+
if (semanticResults.length === 0) {
|
|
20
|
+
return keywordResults.slice(0, limit);
|
|
21
|
+
}
|
|
22
|
+
return HybridKbSearchService.fuseRRF(keywordResults, semanticResults, limit);
|
|
23
|
+
}
|
|
24
|
+
close() {
|
|
25
|
+
this.semantic.close();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Reciprocal Rank Fusion (RRF) — merges two ranked result lists.
|
|
29
|
+
*
|
|
30
|
+
* For each result at rank r (0-indexed):
|
|
31
|
+
* rrfScore(chunk) += 1 / (k + r + 1) where k = 60
|
|
32
|
+
*
|
|
33
|
+
* Deduplicates by chunk URL. When a chunk appears in both sets,
|
|
34
|
+
* keeps the keyword SearchResult (it has query-highlighted snippets).
|
|
35
|
+
* Normalizes final scores to 0–1 range.
|
|
36
|
+
*/
|
|
37
|
+
static fuseRRF(keyword, semantic, limit) {
|
|
38
|
+
const scores = new Map();
|
|
39
|
+
const results = new Map();
|
|
40
|
+
// Accumulate keyword scores (preferred source for snippets)
|
|
41
|
+
for (let r = 0; r < keyword.length; r++) {
|
|
42
|
+
const key = keyword[r].chunk.url;
|
|
43
|
+
const rrfScore = 1 / (RRF_K + r + 1);
|
|
44
|
+
scores.set(key, (scores.get(key) ?? 0) + rrfScore);
|
|
45
|
+
results.set(key, keyword[r]);
|
|
46
|
+
}
|
|
47
|
+
// Accumulate semantic scores (don't overwrite keyword results)
|
|
48
|
+
for (let r = 0; r < semantic.length; r++) {
|
|
49
|
+
const key = semantic[r].chunk.url;
|
|
50
|
+
const rrfScore = 1 / (RRF_K + r + 1);
|
|
51
|
+
scores.set(key, (scores.get(key) ?? 0) + rrfScore);
|
|
52
|
+
if (!results.has(key)) {
|
|
53
|
+
results.set(key, semantic[r]);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// Sort by accumulated RRF score descending
|
|
57
|
+
const sorted = [...scores.entries()].sort((a, b) => b[1] - a[1]);
|
|
58
|
+
const topRrfScore = sorted.length > 0 ? sorted[0][1] : 1;
|
|
59
|
+
return sorted.slice(0, limit).map(([key, rrfScore]) => {
|
|
60
|
+
const result = results.get(key);
|
|
61
|
+
return {
|
|
62
|
+
chunk: result.chunk,
|
|
63
|
+
snippet: result.snippet,
|
|
64
|
+
score: Number((rrfScore / topRrfScore).toFixed(4)),
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=kb-hybrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"kb-hybrid.js","sourceRoot":"","sources":["../src/kb-hybrid.ts"],"names":[],"mappings":"AAGA,MAAM,KAAK,GAAG,EAAE,CAAC;AACjB,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAE3B,MAAM,OAAO,qBAAqB;IAEb;IACA;IAFnB,YACmB,OAAwB,EACxB,QAAiC;QADjC,YAAO,GAAP,OAAO,CAAiB;QACxB,aAAQ,GAAR,QAAQ,CAAyB;IACjD,CAAC;IAEJ,KAAK,CAAC,MAAM,CAAC,KAAa,EAAE,KAAK,GAAG,CAAC;QACnC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QAC3C,CAAC;QAED,MAAM,UAAU,GAAG,KAAK,GAAG,gBAAgB,CAAC;QAC5C,MAAM,CAAC,cAAc,EAAE,eAAe,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1D,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;YACvD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,KAAK,EAAE,UAAU,CAAC;SACxC,CAAC,CAAC;QAEH,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,cAAc,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACxC,CAAC;QAED,OAAO,qBAAqB,CAAC,OAAO,CAAC,cAAc,EAAE,eAAe,EAAE,KAAK,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK;QACH,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxB,CAAC;IAED;;;;;;;;;OASG;IACH,MAAM,CAAC,OAAO,CAAC,OAAuB,EAAE,QAAwB,EAAE,KAAa;QAC7E,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;QAEhD,4DAA4D;QAC5D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;YACjC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,CAAC;QAED,+DAA+D;QAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACzC,MAAM,GAAG,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;YAClC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACrC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC;YACnD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAEzD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,EAAE,EAAE;YACpD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;YACjC,OAAO;gBACL,KAAK,EAAE,MAAM,CAAC,KAAK;gBACnB,OAAO,EAAE,MAAM,CAAC,OAAO;gBACvB,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,GAAG,WAAW,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;aACnD,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SearchResult } from './kb-search.js';
|
|
2
|
+
export declare class SemanticKbSearchService {
|
|
3
|
+
private _isReady;
|
|
4
|
+
private _initPromise;
|
|
5
|
+
private _collection;
|
|
6
|
+
private _extractor;
|
|
7
|
+
private _chunks;
|
|
8
|
+
private _hasLoadedNativeRuntime;
|
|
9
|
+
constructor(kbJsonPath: string, vectorsDir: string);
|
|
10
|
+
isReady(): boolean;
|
|
11
|
+
waitReady(): Promise<boolean>;
|
|
12
|
+
hasNativeRuntimeLoaded(): boolean;
|
|
13
|
+
search(query: string, limit?: number): Promise<SearchResult[]>;
|
|
14
|
+
close(): void;
|
|
15
|
+
private _init;
|
|
16
|
+
}
|