@attrove/mcp 0.1.4 → 0.1.6
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/cjs/{src/__mocks__ → __mocks__}/version.js +1 -2
- package/cjs/{src/constants.js → constants.js} +0 -1
- package/cjs/{src/index.js → index.js} +11 -12
- package/cjs/package.json +1 -69
- package/cjs/{src/server.js → server.js} +45 -40
- package/cjs/{src/tools → tools}/index.js +12 -13
- package/cjs/{src/tools → tools}/integrations.js +7 -6
- package/cjs/{src/tools → tools}/query.js +11 -12
- package/cjs/{src/tools → tools}/search.js +26 -25
- package/cjs/{src/version.js → version.js} +13 -12
- package/{types/src → esm}/__mocks__/version.d.ts +1 -0
- package/esm/__mocks__/version.d.ts.map +1 -0
- package/esm/{src/__mocks__ → __mocks__}/version.js +1 -1
- package/esm/__mocks__/version.js.map +1 -0
- package/{types/src → esm}/constants.d.ts +1 -0
- package/esm/constants.d.ts.map +1 -0
- package/esm/constants.js.map +1 -0
- package/{types/src → esm}/index.d.ts +5 -4
- package/esm/index.d.ts.map +1 -0
- package/esm/{src/index.js → index.js} +3 -3
- package/esm/index.js.map +1 -0
- package/esm/package.json +1 -69
- package/{types/src → esm}/server.d.ts +2 -1
- package/esm/server.d.ts.map +1 -0
- package/esm/{src/server.js → server.js} +44 -38
- package/esm/server.js.map +1 -0
- package/{types/src → esm}/tools/index.d.ts +4 -3
- package/esm/tools/index.d.ts.map +1 -0
- package/esm/{src/tools → tools}/index.js +3 -3
- package/esm/tools/index.js.map +1 -0
- package/{types/src → esm}/tools/integrations.d.ts +2 -1
- package/esm/tools/integrations.d.ts.map +1 -0
- package/esm/{src/tools → tools}/integrations.js +7 -5
- package/esm/tools/integrations.js.map +1 -0
- package/{types/src → esm}/tools/query.d.ts +2 -1
- package/esm/tools/query.d.ts.map +1 -0
- package/esm/{src/tools → tools}/query.js +11 -11
- package/esm/tools/query.js.map +1 -0
- package/{types/src → esm}/tools/search.d.ts +2 -1
- package/esm/tools/search.d.ts.map +1 -0
- package/esm/{src/tools → tools}/search.js +25 -23
- package/esm/tools/search.js.map +1 -0
- package/{types/src → esm}/version.d.ts +1 -0
- package/esm/version.d.ts.map +1 -0
- package/esm/{src/version.js → version.js} +16 -14
- package/esm/version.js.map +1 -0
- package/package.json +7 -6
- package/cjs/README.md +0 -247
- package/cjs/bin/attrove-mcp.js +0 -69
- package/cjs/src/__mocks__/version.js.map +0 -1
- package/cjs/src/constants.js.map +0 -1
- package/cjs/src/index.js.map +0 -1
- package/cjs/src/server.js.map +0 -1
- package/cjs/src/tools/index.js.map +0 -1
- package/cjs/src/tools/integrations.js.map +0 -1
- package/cjs/src/tools/query.js.map +0 -1
- package/cjs/src/tools/search.js.map +0 -1
- package/cjs/src/version.js.map +0 -1
- package/esm/README.md +0 -247
- package/esm/bin/attrove-mcp.js +0 -69
- package/esm/src/__mocks__/version.js.map +0 -1
- package/esm/src/constants.js.map +0 -1
- package/esm/src/index.js.map +0 -1
- package/esm/src/server.js.map +0 -1
- package/esm/src/tools/index.js.map +0 -1
- package/esm/src/tools/integrations.js.map +0 -1
- package/esm/src/tools/query.js.map +0 -1
- package/esm/src/tools/search.js.map +0 -1
- package/esm/src/version.js.map +0 -1
- /package/esm/{src/constants.js → constants.js} +0 -0
|
@@ -7,11 +7,10 @@
|
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.resetVersionCache = exports.getVersion = void 0;
|
|
9
9
|
function getVersion() {
|
|
10
|
-
return
|
|
10
|
+
return "1.0.0-test";
|
|
11
11
|
}
|
|
12
12
|
exports.getVersion = getVersion;
|
|
13
13
|
function resetVersionCache() {
|
|
14
14
|
// No-op in mock
|
|
15
15
|
}
|
|
16
16
|
exports.resetVersionCache = resetVersionCache;
|
|
17
|
-
//# sourceMappingURL=version.js.map
|
|
@@ -29,15 +29,14 @@
|
|
|
29
29
|
*/
|
|
30
30
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
31
31
|
exports.getVersion = exports.integrationsToolDefinition = exports.searchToolDefinition = exports.queryToolDefinition = exports.allToolDefinitions = exports.getConfigFromEnv = exports.startServer = exports.createServer = void 0;
|
|
32
|
-
var
|
|
33
|
-
Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return
|
|
34
|
-
Object.defineProperty(exports, "startServer", { enumerable: true, get: function () { return
|
|
35
|
-
Object.defineProperty(exports, "getConfigFromEnv", { enumerable: true, get: function () { return
|
|
36
|
-
var
|
|
37
|
-
Object.defineProperty(exports, "allToolDefinitions", { enumerable: true, get: function () { return
|
|
38
|
-
Object.defineProperty(exports, "queryToolDefinition", { enumerable: true, get: function () { return
|
|
39
|
-
Object.defineProperty(exports, "searchToolDefinition", { enumerable: true, get: function () { return
|
|
40
|
-
Object.defineProperty(exports, "integrationsToolDefinition", { enumerable: true, get: function () { return
|
|
41
|
-
var
|
|
42
|
-
Object.defineProperty(exports, "getVersion", { enumerable: true, get: function () { return
|
|
43
|
-
//# sourceMappingURL=index.js.map
|
|
32
|
+
var server_js_1 = require("./server.js");
|
|
33
|
+
Object.defineProperty(exports, "createServer", { enumerable: true, get: function () { return server_js_1.createServer; } });
|
|
34
|
+
Object.defineProperty(exports, "startServer", { enumerable: true, get: function () { return server_js_1.startServer; } });
|
|
35
|
+
Object.defineProperty(exports, "getConfigFromEnv", { enumerable: true, get: function () { return server_js_1.getConfigFromEnv; } });
|
|
36
|
+
var index_js_1 = require("./tools/index.js");
|
|
37
|
+
Object.defineProperty(exports, "allToolDefinitions", { enumerable: true, get: function () { return index_js_1.allToolDefinitions; } });
|
|
38
|
+
Object.defineProperty(exports, "queryToolDefinition", { enumerable: true, get: function () { return index_js_1.queryToolDefinition; } });
|
|
39
|
+
Object.defineProperty(exports, "searchToolDefinition", { enumerable: true, get: function () { return index_js_1.searchToolDefinition; } });
|
|
40
|
+
Object.defineProperty(exports, "integrationsToolDefinition", { enumerable: true, get: function () { return index_js_1.integrationsToolDefinition; } });
|
|
41
|
+
var version_js_1 = require("./version.js");
|
|
42
|
+
Object.defineProperty(exports, "getVersion", { enumerable: true, get: function () { return version_js_1.getVersion; } });
|
package/cjs/package.json
CHANGED
|
@@ -1,69 +1 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@attrove/mcp",
|
|
3
|
-
"version": "0.1.4",
|
|
4
|
-
"description": "MCP server for Attrove - AI-powered context retrieval for Claude and Cursor",
|
|
5
|
-
"main": "./dist/cjs/index.js",
|
|
6
|
-
"module": "./dist/esm/index.js",
|
|
7
|
-
"types": "./dist/types/index.d.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"attrove-mcp": "./bin/attrove-mcp.js"
|
|
10
|
-
},
|
|
11
|
-
"exports": {
|
|
12
|
-
".": {
|
|
13
|
-
"import": {
|
|
14
|
-
"types": "./dist/types/index.d.ts",
|
|
15
|
-
"default": "./dist/esm/index.js"
|
|
16
|
-
},
|
|
17
|
-
"require": {
|
|
18
|
-
"types": "./dist/types/index.d.ts",
|
|
19
|
-
"default": "./dist/cjs/index.js"
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
},
|
|
23
|
-
"files": [
|
|
24
|
-
"dist",
|
|
25
|
-
"bin",
|
|
26
|
-
"README.md"
|
|
27
|
-
],
|
|
28
|
-
"sideEffects": false,
|
|
29
|
-
"keywords": [
|
|
30
|
-
"attrove",
|
|
31
|
-
"mcp",
|
|
32
|
-
"model-context-protocol",
|
|
33
|
-
"claude",
|
|
34
|
-
"cursor",
|
|
35
|
-
"ai",
|
|
36
|
-
"rag",
|
|
37
|
-
"llm"
|
|
38
|
-
],
|
|
39
|
-
"author": "Attrove <support@attrove.com>",
|
|
40
|
-
"license": "MIT",
|
|
41
|
-
"repository": {
|
|
42
|
-
"type": "git",
|
|
43
|
-
"url": "https://github.com/attrove/attrove-js.git",
|
|
44
|
-
"directory": "packages/mcp"
|
|
45
|
-
},
|
|
46
|
-
"homepage": "https://attrove.com/docs/mcp",
|
|
47
|
-
"bugs": {
|
|
48
|
-
"url": "https://github.com/attrove/attrove-js/issues"
|
|
49
|
-
},
|
|
50
|
-
"engines": {
|
|
51
|
-
"node": ">=18.0.0"
|
|
52
|
-
},
|
|
53
|
-
"scripts": {
|
|
54
|
-
"build": "nx build mcp",
|
|
55
|
-
"test": "nx test mcp"
|
|
56
|
-
},
|
|
57
|
-
"dependencies": {
|
|
58
|
-
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
59
|
-
"@attrove/sdk": "*"
|
|
60
|
-
},
|
|
61
|
-
"devDependencies": {
|
|
62
|
-
"@types/node": "^20.0.0",
|
|
63
|
-
"typescript": "~5.7.0"
|
|
64
|
-
},
|
|
65
|
-
"publishConfig": {
|
|
66
|
-
"access": "public"
|
|
67
|
-
},
|
|
68
|
-
"type": "commonjs"
|
|
69
|
-
}
|
|
1
|
+
{"type": "commonjs"}
|
|
@@ -11,8 +11,8 @@ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
|
|
|
11
11
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
12
12
|
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
|
|
13
13
|
const sdk_1 = require("@attrove/sdk");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
14
|
+
const index_js_2 = require("./tools/index.js");
|
|
15
|
+
const version_js_1 = require("./version.js");
|
|
16
16
|
/**
|
|
17
17
|
* Validate that a value is an array of strings.
|
|
18
18
|
* Returns undefined if value is null/undefined.
|
|
@@ -25,8 +25,8 @@ function validateStringArray(value, fieldName) {
|
|
|
25
25
|
if (!Array.isArray(value)) {
|
|
26
26
|
throw new sdk_1.ValidationError(`${fieldName} must be an array of strings, received ${typeof value}`, sdk_1.ErrorCodes.VALIDATION_INVALID_FORMAT, { field: fieldName, received: typeof value });
|
|
27
27
|
}
|
|
28
|
-
if (!value.every((item) => typeof item ===
|
|
29
|
-
const types = value.map(item => typeof item).join(
|
|
28
|
+
if (!value.every((item) => typeof item === "string")) {
|
|
29
|
+
const types = value.map((item) => typeof item).join(", ");
|
|
30
30
|
throw new sdk_1.ValidationError(`${fieldName} must contain only strings, received types: [${types}]`, sdk_1.ErrorCodes.VALIDATION_INVALID_FORMAT, { field: fieldName, receivedTypes: types });
|
|
31
31
|
}
|
|
32
32
|
return value;
|
|
@@ -37,17 +37,19 @@ function validateStringArray(value, fieldName) {
|
|
|
37
37
|
* @throws {ValidationError} If arguments are missing or invalid
|
|
38
38
|
*/
|
|
39
39
|
function validateQueryInput(args) {
|
|
40
|
-
if (!args || typeof args !==
|
|
41
|
-
throw new sdk_1.ValidationError('Missing or invalid arguments. Expected an object with a "query" field.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { expected:
|
|
40
|
+
if (!args || typeof args !== "object") {
|
|
41
|
+
throw new sdk_1.ValidationError('Missing or invalid arguments. Expected an object with a "query" field.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { expected: "object with query field", received: typeof args });
|
|
42
42
|
}
|
|
43
43
|
const input = args;
|
|
44
|
-
if (typeof input.query !==
|
|
45
|
-
throw new sdk_1.ValidationError('Missing required parameter "query". Please provide a question to ask.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { field:
|
|
44
|
+
if (typeof input.query !== "string" || input.query.trim() === "") {
|
|
45
|
+
throw new sdk_1.ValidationError('Missing required parameter "query". Please provide a question to ask.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { field: "query" });
|
|
46
46
|
}
|
|
47
47
|
return {
|
|
48
48
|
query: input.query,
|
|
49
|
-
integration_ids: validateStringArray(input.integration_ids,
|
|
50
|
-
include_sources: typeof input.include_sources ===
|
|
49
|
+
integration_ids: validateStringArray(input.integration_ids, "integration_ids"),
|
|
50
|
+
include_sources: typeof input.include_sources === "boolean"
|
|
51
|
+
? input.include_sources
|
|
52
|
+
: undefined,
|
|
51
53
|
};
|
|
52
54
|
}
|
|
53
55
|
/**
|
|
@@ -56,19 +58,21 @@ function validateQueryInput(args) {
|
|
|
56
58
|
* @throws {ValidationError} If arguments are missing or invalid
|
|
57
59
|
*/
|
|
58
60
|
function validateSearchInput(args) {
|
|
59
|
-
if (!args || typeof args !==
|
|
60
|
-
throw new sdk_1.ValidationError('Missing or invalid arguments. Expected an object with a "query" field.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { expected:
|
|
61
|
+
if (!args || typeof args !== "object") {
|
|
62
|
+
throw new sdk_1.ValidationError('Missing or invalid arguments. Expected an object with a "query" field.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { expected: "object with query field", received: typeof args });
|
|
61
63
|
}
|
|
62
64
|
const input = args;
|
|
63
|
-
if (typeof input.query !==
|
|
64
|
-
throw new sdk_1.ValidationError('Missing required parameter "query". Please provide a search query.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { field:
|
|
65
|
+
if (typeof input.query !== "string" || input.query.trim() === "") {
|
|
66
|
+
throw new sdk_1.ValidationError('Missing required parameter "query". Please provide a search query.', sdk_1.ErrorCodes.VALIDATION_REQUIRED_FIELD, { field: "query" });
|
|
65
67
|
}
|
|
66
68
|
return {
|
|
67
69
|
query: input.query,
|
|
68
|
-
after_date: typeof input.after_date ===
|
|
69
|
-
before_date: typeof input.before_date ===
|
|
70
|
-
sender_domains: validateStringArray(input.sender_domains,
|
|
71
|
-
include_body_text: typeof input.include_body_text ===
|
|
70
|
+
after_date: typeof input.after_date === "string" ? input.after_date : undefined,
|
|
71
|
+
before_date: typeof input.before_date === "string" ? input.before_date : undefined,
|
|
72
|
+
sender_domains: validateStringArray(input.sender_domains, "sender_domains"),
|
|
73
|
+
include_body_text: typeof input.include_body_text === "boolean"
|
|
74
|
+
? input.include_body_text
|
|
75
|
+
: undefined,
|
|
72
76
|
};
|
|
73
77
|
}
|
|
74
78
|
/**
|
|
@@ -92,12 +96,14 @@ function formatErrorResponse(error) {
|
|
|
92
96
|
detailParts.push(`Details: ${JSON.stringify(error.details)}`);
|
|
93
97
|
}
|
|
94
98
|
catch (serializeError) {
|
|
95
|
-
const reason = serializeError instanceof Error
|
|
99
|
+
const reason = serializeError instanceof Error
|
|
100
|
+
? serializeError.message
|
|
101
|
+
: "Unknown reason";
|
|
96
102
|
detailParts.push(`Details: [Not serializable: ${reason}]`);
|
|
97
103
|
}
|
|
98
104
|
}
|
|
99
105
|
if (detailParts.length > 0) {
|
|
100
|
-
errorDetails = detailParts.join(
|
|
106
|
+
errorDetails = detailParts.join("\n");
|
|
101
107
|
}
|
|
102
108
|
}
|
|
103
109
|
else if (error instanceof Error) {
|
|
@@ -110,7 +116,7 @@ function formatErrorResponse(error) {
|
|
|
110
116
|
? `Error: ${errorMessage}\n\n${errorDetails}`
|
|
111
117
|
: `Error: ${errorMessage}`;
|
|
112
118
|
return {
|
|
113
|
-
content: [{ type:
|
|
119
|
+
content: [{ type: "text", text }],
|
|
114
120
|
isError: true,
|
|
115
121
|
};
|
|
116
122
|
}
|
|
@@ -119,8 +125,8 @@ function formatErrorResponse(error) {
|
|
|
119
125
|
*/
|
|
120
126
|
function createServer(config) {
|
|
121
127
|
const server = new index_js_1.Server({
|
|
122
|
-
name:
|
|
123
|
-
version: (0,
|
|
128
|
+
name: "attrove",
|
|
129
|
+
version: (0, version_js_1.getVersion)(),
|
|
124
130
|
}, {
|
|
125
131
|
capabilities: {
|
|
126
132
|
tools: {},
|
|
@@ -136,7 +142,7 @@ function createServer(config) {
|
|
|
136
142
|
// Register tool list handler
|
|
137
143
|
server.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => {
|
|
138
144
|
return {
|
|
139
|
-
tools:
|
|
145
|
+
tools: index_js_2.allToolDefinitions.map((tool) => ({
|
|
140
146
|
name: tool.name,
|
|
141
147
|
description: tool.description,
|
|
142
148
|
inputSchema: tool.inputSchema,
|
|
@@ -150,20 +156,20 @@ function createServer(config) {
|
|
|
150
156
|
// and programming bugs in validation don't get caught as API errors
|
|
151
157
|
let validatedInput;
|
|
152
158
|
switch (name) {
|
|
153
|
-
case
|
|
159
|
+
case "attrove_query":
|
|
154
160
|
validatedInput = validateQueryInput(args);
|
|
155
161
|
break;
|
|
156
|
-
case
|
|
162
|
+
case "attrove_search":
|
|
157
163
|
validatedInput = validateSearchInput(args);
|
|
158
164
|
break;
|
|
159
|
-
case
|
|
165
|
+
case "attrove_integrations":
|
|
160
166
|
// No input validation needed
|
|
161
167
|
break;
|
|
162
168
|
default:
|
|
163
169
|
return {
|
|
164
170
|
content: [
|
|
165
171
|
{
|
|
166
|
-
type:
|
|
172
|
+
type: "text",
|
|
167
173
|
text: `Unknown tool: ${name}. Available tools: attrove_query, attrove_search, attrove_integrations`,
|
|
168
174
|
},
|
|
169
175
|
],
|
|
@@ -174,14 +180,14 @@ function createServer(config) {
|
|
|
174
180
|
try {
|
|
175
181
|
let result;
|
|
176
182
|
switch (name) {
|
|
177
|
-
case
|
|
178
|
-
result = await (0,
|
|
183
|
+
case "attrove_query":
|
|
184
|
+
result = await (0, index_js_2.executeQueryTool)(client, validatedInput);
|
|
179
185
|
break;
|
|
180
|
-
case
|
|
181
|
-
result = await (0,
|
|
186
|
+
case "attrove_search":
|
|
187
|
+
result = await (0, index_js_2.executeSearchTool)(client, validatedInput);
|
|
182
188
|
break;
|
|
183
|
-
case
|
|
184
|
-
result = await (0,
|
|
189
|
+
case "attrove_integrations":
|
|
190
|
+
result = await (0, index_js_2.executeIntegrationsTool)(client);
|
|
185
191
|
break;
|
|
186
192
|
default:
|
|
187
193
|
// Already handled above, but TypeScript needs this
|
|
@@ -190,7 +196,7 @@ function createServer(config) {
|
|
|
190
196
|
return {
|
|
191
197
|
content: [
|
|
192
198
|
{
|
|
193
|
-
type:
|
|
199
|
+
type: "text",
|
|
194
200
|
text: result,
|
|
195
201
|
},
|
|
196
202
|
],
|
|
@@ -230,12 +236,12 @@ function getConfigFromEnv() {
|
|
|
230
236
|
const userId = process.env.ATTROVE_USER_ID;
|
|
231
237
|
const baseUrl = process.env.ATTROVE_BASE_URL;
|
|
232
238
|
if (!apiKey) {
|
|
233
|
-
throw new Error(
|
|
234
|
-
|
|
239
|
+
throw new Error("ATTROVE_API_KEY environment variable is required. " +
|
|
240
|
+
"Set it to your Attrove API key (sk_...).");
|
|
235
241
|
}
|
|
236
242
|
if (!userId) {
|
|
237
|
-
throw new Error(
|
|
238
|
-
|
|
243
|
+
throw new Error("ATTROVE_USER_ID environment variable is required. " +
|
|
244
|
+
"Set it to the user ID (UUID) for the user whose context you want to access.");
|
|
239
245
|
}
|
|
240
246
|
return {
|
|
241
247
|
apiKey,
|
|
@@ -244,4 +250,3 @@ function getConfigFromEnv() {
|
|
|
244
250
|
};
|
|
245
251
|
}
|
|
246
252
|
exports.getConfigFromEnv = getConfigFromEnv;
|
|
247
|
-
//# sourceMappingURL=server.js.map
|
|
@@ -6,21 +6,20 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.allToolDefinitions = exports.executeIntegrationsTool = exports.integrationsToolDefinition = exports.executeSearchTool = exports.searchToolDefinition = exports.executeQueryTool = exports.queryToolDefinition = void 0;
|
|
9
|
-
const
|
|
10
|
-
Object.defineProperty(exports, "queryToolDefinition", { enumerable: true, get: function () { return
|
|
11
|
-
Object.defineProperty(exports, "executeQueryTool", { enumerable: true, get: function () { return
|
|
12
|
-
const
|
|
13
|
-
Object.defineProperty(exports, "searchToolDefinition", { enumerable: true, get: function () { return
|
|
14
|
-
Object.defineProperty(exports, "executeSearchTool", { enumerable: true, get: function () { return
|
|
15
|
-
const
|
|
16
|
-
Object.defineProperty(exports, "integrationsToolDefinition", { enumerable: true, get: function () { return
|
|
17
|
-
Object.defineProperty(exports, "executeIntegrationsTool", { enumerable: true, get: function () { return
|
|
9
|
+
const query_js_1 = require("./query.js");
|
|
10
|
+
Object.defineProperty(exports, "queryToolDefinition", { enumerable: true, get: function () { return query_js_1.queryToolDefinition; } });
|
|
11
|
+
Object.defineProperty(exports, "executeQueryTool", { enumerable: true, get: function () { return query_js_1.executeQueryTool; } });
|
|
12
|
+
const search_js_1 = require("./search.js");
|
|
13
|
+
Object.defineProperty(exports, "searchToolDefinition", { enumerable: true, get: function () { return search_js_1.searchToolDefinition; } });
|
|
14
|
+
Object.defineProperty(exports, "executeSearchTool", { enumerable: true, get: function () { return search_js_1.executeSearchTool; } });
|
|
15
|
+
const integrations_js_1 = require("./integrations.js");
|
|
16
|
+
Object.defineProperty(exports, "integrationsToolDefinition", { enumerable: true, get: function () { return integrations_js_1.integrationsToolDefinition; } });
|
|
17
|
+
Object.defineProperty(exports, "executeIntegrationsTool", { enumerable: true, get: function () { return integrations_js_1.executeIntegrationsTool; } });
|
|
18
18
|
/**
|
|
19
19
|
* All tool definitions for registration with MCP.
|
|
20
20
|
*/
|
|
21
21
|
exports.allToolDefinitions = [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
query_js_1.queryToolDefinition,
|
|
23
|
+
search_js_1.searchToolDefinition,
|
|
24
|
+
integrations_js_1.integrationsToolDefinition,
|
|
25
25
|
];
|
|
26
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -10,7 +10,7 @@ exports.executeIntegrationsTool = exports.integrationsToolDefinition = void 0;
|
|
|
10
10
|
* Tool definition for attrove_integrations.
|
|
11
11
|
*/
|
|
12
12
|
exports.integrationsToolDefinition = {
|
|
13
|
-
name:
|
|
13
|
+
name: "attrove_integrations",
|
|
14
14
|
description: `List the user's connected integrations (Gmail, Slack, etc.).
|
|
15
15
|
|
|
16
16
|
This tool shows which services the user has connected and their current status. Use this to:
|
|
@@ -23,7 +23,7 @@ The response includes:
|
|
|
23
23
|
- Provider name (gmail, slack, google_calendar, etc.)
|
|
24
24
|
- Connection status (connected, disconnected, expired, error, pending)`,
|
|
25
25
|
inputSchema: {
|
|
26
|
-
type:
|
|
26
|
+
type: "object",
|
|
27
27
|
properties: {},
|
|
28
28
|
required: [],
|
|
29
29
|
},
|
|
@@ -34,12 +34,14 @@ The response includes:
|
|
|
34
34
|
async function executeIntegrationsTool(client) {
|
|
35
35
|
const integrations = await client.integrations.list();
|
|
36
36
|
if (integrations.length === 0) {
|
|
37
|
-
return
|
|
37
|
+
return "No integrations connected. The user needs to connect their Gmail, Slack, or other services first.";
|
|
38
38
|
}
|
|
39
39
|
let result = `Connected integrations (${integrations.length}):\n`;
|
|
40
40
|
for (const integration of integrations) {
|
|
41
|
-
const status = integration.is_active ?
|
|
42
|
-
const authStatus = integration.auth_status ===
|
|
41
|
+
const status = integration.is_active ? "[Active]" : "[Inactive]";
|
|
42
|
+
const authStatus = integration.auth_status === "connected"
|
|
43
|
+
? ""
|
|
44
|
+
: ` (${integration.auth_status})`;
|
|
43
45
|
result += `\n- **${integration.name}** (${integration.provider})\n`;
|
|
44
46
|
result += ` - ID: ${integration.id}\n`;
|
|
45
47
|
result += ` - Status: ${status}${authStatus}\n`;
|
|
@@ -47,4 +49,3 @@ async function executeIntegrationsTool(client) {
|
|
|
47
49
|
return result;
|
|
48
50
|
}
|
|
49
51
|
exports.executeIntegrationsTool = executeIntegrationsTool;
|
|
50
|
-
//# sourceMappingURL=integrations.js.map
|
|
@@ -10,7 +10,7 @@ exports.executeQueryTool = exports.queryToolDefinition = void 0;
|
|
|
10
10
|
* Tool definition for attrove_query.
|
|
11
11
|
*/
|
|
12
12
|
exports.queryToolDefinition = {
|
|
13
|
-
name:
|
|
13
|
+
name: "attrove_query",
|
|
14
14
|
description: `Ask a question about the user's communications and get an AI-generated answer.
|
|
15
15
|
|
|
16
16
|
This tool searches across all connected integrations (Gmail, Slack, Google Meet, etc.) and returns a comprehensive answer based on the relevant context.
|
|
@@ -21,24 +21,24 @@ Use this tool when the user asks questions like:
|
|
|
21
21
|
- "What are the action items from yesterday's standup?"
|
|
22
22
|
- "When is my next meeting with John?"`,
|
|
23
23
|
inputSchema: {
|
|
24
|
-
type:
|
|
24
|
+
type: "object",
|
|
25
25
|
properties: {
|
|
26
26
|
query: {
|
|
27
|
-
type:
|
|
28
|
-
description:
|
|
27
|
+
type: "string",
|
|
28
|
+
description: "The question to ask about the user's context",
|
|
29
29
|
},
|
|
30
30
|
integration_ids: {
|
|
31
|
-
type:
|
|
32
|
-
items: { type:
|
|
33
|
-
description:
|
|
31
|
+
type: "array",
|
|
32
|
+
items: { type: "string" },
|
|
33
|
+
description: "Optional: Filter to specific integration IDs (UUIDs)",
|
|
34
34
|
},
|
|
35
35
|
include_sources: {
|
|
36
|
-
type:
|
|
37
|
-
description:
|
|
36
|
+
type: "boolean",
|
|
37
|
+
description: "Optional: Include source snippets in the response",
|
|
38
38
|
default: false,
|
|
39
39
|
},
|
|
40
40
|
},
|
|
41
|
-
required: [
|
|
41
|
+
required: ["query"],
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
44
|
/**
|
|
@@ -56,7 +56,7 @@ async function executeQueryTool(client, input) {
|
|
|
56
56
|
// Format the response for MCP
|
|
57
57
|
let result = response.answer;
|
|
58
58
|
if (response.sources?.length) {
|
|
59
|
-
result +=
|
|
59
|
+
result += "\n\n**Sources:**";
|
|
60
60
|
for (const source of response.sources) {
|
|
61
61
|
result += `\n- ${source.title}: "${source.snippet}"`;
|
|
62
62
|
}
|
|
@@ -67,4 +67,3 @@ async function executeQueryTool(client, input) {
|
|
|
67
67
|
return result;
|
|
68
68
|
}
|
|
69
69
|
exports.executeQueryTool = executeQueryTool;
|
|
70
|
-
//# sourceMappingURL=query.js.map
|
|
@@ -6,12 +6,12 @@
|
|
|
6
6
|
*/
|
|
7
7
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
8
|
exports.executeSearchTool = exports.searchToolDefinition = void 0;
|
|
9
|
-
const
|
|
9
|
+
const constants_js_1 = require("../constants.js");
|
|
10
10
|
/**
|
|
11
11
|
* Tool definition for attrove_search.
|
|
12
12
|
*/
|
|
13
13
|
exports.searchToolDefinition = {
|
|
14
|
-
name:
|
|
14
|
+
name: "attrove_search",
|
|
15
15
|
description: `Search for specific messages or conversations in the user's communications.
|
|
16
16
|
|
|
17
17
|
This tool performs semantic search across connected integrations and returns matching messages grouped by conversation. Use this when you need:
|
|
@@ -24,32 +24,32 @@ Use this tool when the user asks things like:
|
|
|
24
24
|
- "Show me conversations with the marketing team"
|
|
25
25
|
- "Search for messages mentioning the deadline"`,
|
|
26
26
|
inputSchema: {
|
|
27
|
-
type:
|
|
27
|
+
type: "object",
|
|
28
28
|
properties: {
|
|
29
29
|
query: {
|
|
30
|
-
type:
|
|
31
|
-
description:
|
|
30
|
+
type: "string",
|
|
31
|
+
description: "The search query (semantic, not keyword-based)",
|
|
32
32
|
},
|
|
33
33
|
after_date: {
|
|
34
|
-
type:
|
|
35
|
-
description:
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "Optional: Only include messages after this date (ISO 8601)",
|
|
36
36
|
},
|
|
37
37
|
before_date: {
|
|
38
|
-
type:
|
|
39
|
-
description:
|
|
38
|
+
type: "string",
|
|
39
|
+
description: "Optional: Only include messages before this date (ISO 8601)",
|
|
40
40
|
},
|
|
41
41
|
sender_domains: {
|
|
42
|
-
type:
|
|
43
|
-
items: { type:
|
|
42
|
+
type: "array",
|
|
43
|
+
items: { type: "string" },
|
|
44
44
|
description: 'Optional: Filter by sender email domains (e.g., ["acme.com"])',
|
|
45
45
|
},
|
|
46
46
|
include_body_text: {
|
|
47
|
-
type:
|
|
48
|
-
description:
|
|
47
|
+
type: "boolean",
|
|
48
|
+
description: "Optional: Include full message body text",
|
|
49
49
|
default: true,
|
|
50
50
|
},
|
|
51
51
|
},
|
|
52
|
-
required: [
|
|
52
|
+
required: ["query"],
|
|
53
53
|
},
|
|
54
54
|
};
|
|
55
55
|
/**
|
|
@@ -75,7 +75,7 @@ async function executeSearchTool(client, input) {
|
|
|
75
75
|
return `No messages found matching "${input.query}".`;
|
|
76
76
|
}
|
|
77
77
|
// Defensive check for conversations structure
|
|
78
|
-
if (!response.conversations || typeof response.conversations !==
|
|
78
|
+
if (!response.conversations || typeof response.conversations !== "object") {
|
|
79
79
|
return `Found ${messageCount} messages, but conversation data is unavailable.`;
|
|
80
80
|
}
|
|
81
81
|
const conversationCount = Object.keys(response.conversations).length;
|
|
@@ -107,22 +107,24 @@ async function executeSearchTool(client, input) {
|
|
|
107
107
|
continue;
|
|
108
108
|
}
|
|
109
109
|
// Defensive date formatting to handle invalid dates gracefully
|
|
110
|
-
let dateStr =
|
|
110
|
+
let dateStr = "Unknown date";
|
|
111
111
|
if (msg.received_at) {
|
|
112
112
|
const parsedDate = new Date(msg.received_at);
|
|
113
|
-
dateStr = Number.isNaN(parsedDate.getTime())
|
|
113
|
+
dateStr = Number.isNaN(parsedDate.getTime())
|
|
114
|
+
? "Invalid date"
|
|
115
|
+
: parsedDate.toLocaleDateString();
|
|
114
116
|
}
|
|
115
|
-
result += `- **${msg.sender_name ||
|
|
117
|
+
result += `- **${msg.sender_name || "Unknown"}** (${dateStr}): `;
|
|
116
118
|
if (msg.body_text) {
|
|
117
|
-
const preview = msg.body_text.length >
|
|
118
|
-
? msg.body_text.substring(0,
|
|
119
|
+
const preview = msg.body_text.length > constants_js_1.MAX_BODY_PREVIEW_LENGTH
|
|
120
|
+
? msg.body_text.substring(0, constants_js_1.MAX_BODY_PREVIEW_LENGTH) + "..."
|
|
119
121
|
: msg.body_text;
|
|
120
|
-
result += preview.replace(/\n/g,
|
|
122
|
+
result += preview.replace(/\n/g, " ");
|
|
121
123
|
}
|
|
122
124
|
else {
|
|
123
|
-
result +=
|
|
125
|
+
result += "[Message content not included]";
|
|
124
126
|
}
|
|
125
|
-
result +=
|
|
127
|
+
result += "\n";
|
|
126
128
|
}
|
|
127
129
|
}
|
|
128
130
|
}
|
|
@@ -139,9 +141,8 @@ async function executeSearchTool(client, input) {
|
|
|
139
141
|
if (skippedMessages > 0) {
|
|
140
142
|
warnings.push(`${skippedMessages} message(s)`);
|
|
141
143
|
}
|
|
142
|
-
result += `\n---\n_Note: ${warnings.join(
|
|
144
|
+
result += `\n---\n_Note: ${warnings.join(", ")} skipped due to incomplete data._\n`;
|
|
143
145
|
}
|
|
144
146
|
return result;
|
|
145
147
|
}
|
|
146
148
|
exports.executeSearchTool = executeSearchTool;
|
|
147
|
-
//# sourceMappingURL=search.js.map
|
|
@@ -17,7 +17,7 @@ const url_1 = require("url");
|
|
|
17
17
|
* Fallback version used when package.json cannot be read.
|
|
18
18
|
* This should only happen in unusual development environments.
|
|
19
19
|
*/
|
|
20
|
-
const FALLBACK_VERSION =
|
|
20
|
+
const FALLBACK_VERSION = "0.0.0-unknown";
|
|
21
21
|
/**
|
|
22
22
|
* Cached version string to avoid repeated file reads.
|
|
23
23
|
*/
|
|
@@ -28,15 +28,15 @@ let cachedVersion;
|
|
|
28
28
|
*/
|
|
29
29
|
function getCurrentDirectory() {
|
|
30
30
|
const err = new Error();
|
|
31
|
-
const stack = err.stack ||
|
|
31
|
+
const stack = err.stack || "";
|
|
32
32
|
// Stack trace line patterns:
|
|
33
33
|
// Node CJS: " at Function.<anonymous> (/path/to/file.js:10:15)"
|
|
34
34
|
// Node ESM: " at file:///path/to/file.js:10:15"
|
|
35
35
|
// Also handles: " at /path/to/file.js:10:15"
|
|
36
|
-
const lines = stack.split(
|
|
36
|
+
const lines = stack.split("\n");
|
|
37
37
|
for (const line of lines) {
|
|
38
38
|
// Skip the Error message line and this function's frame
|
|
39
|
-
if (!line.includes(
|
|
39
|
+
if (!line.includes("getCurrentDirectory") && !line.startsWith("Error")) {
|
|
40
40
|
// Match file:// URLs (ESM)
|
|
41
41
|
const fileUrlMatch = line.match(/file:\/\/([^:]+):\d+:\d+/);
|
|
42
42
|
if (fileUrlMatch) {
|
|
@@ -50,12 +50,14 @@ function getCurrentDirectory() {
|
|
|
50
50
|
}
|
|
51
51
|
// Match parenthesized paths: "at Something (/path/to/file.js:10:15)"
|
|
52
52
|
const parenMatch = line.match(/\(([^)]+):\d+:\d+\)/);
|
|
53
|
-
if (parenMatch && !parenMatch[1].startsWith(
|
|
53
|
+
if (parenMatch && !parenMatch[1].startsWith("node:")) {
|
|
54
54
|
return (0, path_1.dirname)(parenMatch[1]);
|
|
55
55
|
}
|
|
56
56
|
// Match bare paths: "at /path/to/file.js:10:15"
|
|
57
57
|
const bareMatch = line.match(/at\s+([^:]+):\d+:\d+/);
|
|
58
|
-
if (bareMatch &&
|
|
58
|
+
if (bareMatch &&
|
|
59
|
+
!bareMatch[1].startsWith("node:") &&
|
|
60
|
+
!bareMatch[1].includes("(")) {
|
|
59
61
|
return (0, path_1.dirname)(bareMatch[1].trim());
|
|
60
62
|
}
|
|
61
63
|
}
|
|
@@ -70,10 +72,10 @@ function findPackageJson(startDir, packageName) {
|
|
|
70
72
|
const visited = new Set();
|
|
71
73
|
while (dir && !visited.has(dir)) {
|
|
72
74
|
visited.add(dir);
|
|
73
|
-
const pkgPath = (0, path_1.join)(dir,
|
|
75
|
+
const pkgPath = (0, path_1.join)(dir, "package.json");
|
|
74
76
|
if ((0, fs_1.existsSync)(pkgPath)) {
|
|
75
77
|
try {
|
|
76
|
-
const pkg = JSON.parse((0, fs_1.readFileSync)(pkgPath,
|
|
78
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)(pkgPath, "utf-8"));
|
|
77
79
|
if (pkg.name === packageName && pkg.version) {
|
|
78
80
|
return pkg.version;
|
|
79
81
|
}
|
|
@@ -102,7 +104,7 @@ function getVersion() {
|
|
|
102
104
|
if (cachedVersion !== undefined) {
|
|
103
105
|
return cachedVersion;
|
|
104
106
|
}
|
|
105
|
-
const packageName =
|
|
107
|
+
const packageName = "@attrove/mcp";
|
|
106
108
|
// Try to find package.json starting from the current file's directory
|
|
107
109
|
const currentDir = getCurrentDirectory();
|
|
108
110
|
if (currentDir) {
|
|
@@ -114,8 +116,8 @@ function getVersion() {
|
|
|
114
116
|
}
|
|
115
117
|
// Fallback: search from common locations relative to process.cwd()
|
|
116
118
|
const fallbackPaths = [
|
|
117
|
-
(0, path_1.resolve)(process.cwd(),
|
|
118
|
-
(0, path_1.resolve)(process.cwd(),
|
|
119
|
+
(0, path_1.resolve)(process.cwd(), "packages/mcp"),
|
|
120
|
+
(0, path_1.resolve)(process.cwd(), "node_modules/@attrove/mcp"),
|
|
119
121
|
process.cwd(),
|
|
120
122
|
];
|
|
121
123
|
for (const searchPath of fallbackPaths) {
|
|
@@ -139,4 +141,3 @@ function resetVersionCache() {
|
|
|
139
141
|
cachedVersion = undefined;
|
|
140
142
|
}
|
|
141
143
|
exports.resetVersionCache = resetVersionCache;
|
|
142
|
-
//# sourceMappingURL=version.js.map
|