memory-journal-mcp 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.dockerignore +88 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +76 -0
- package/.github/ISSUE_TEMPLATE/config.yml +11 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +89 -0
- package/.github/ISSUE_TEMPLATE/question.md +63 -0
- package/.github/dependabot.yml +110 -0
- package/.github/pull_request_template.md +110 -0
- package/.github/workflows/DOCKER_DEPLOYMENT_SETUP.md +346 -0
- package/.github/workflows/codeql.yml +45 -0
- package/.github/workflows/dependabot-auto-merge.yml +42 -0
- package/.github/workflows/docker-publish.yml +277 -0
- package/.github/workflows/lint-and-test.yml +58 -0
- package/.github/workflows/publish-npm.yml +75 -0
- package/.github/workflows/secrets-scanning.yml +32 -0
- package/.github/workflows/security-update.yml +99 -0
- package/.memory-journal-team.db +0 -0
- package/.trivyignore +18 -0
- package/CHANGELOG.md +19 -0
- package/CODE_OF_CONDUCT.md +128 -0
- package/CONTRIBUTING.md +209 -0
- package/DOCKER_README.md +377 -0
- package/Dockerfile +64 -0
- package/LICENSE +21 -0
- package/README.md +461 -0
- package/SECURITY.md +200 -0
- package/VERSION +1 -0
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +42 -0
- package/dist/cli.js.map +1 -0
- package/dist/constants/ServerInstructions.d.ts +8 -0
- package/dist/constants/ServerInstructions.d.ts.map +1 -0
- package/dist/constants/ServerInstructions.js +26 -0
- package/dist/constants/ServerInstructions.js.map +1 -0
- package/dist/database/SqliteAdapter.d.ts +198 -0
- package/dist/database/SqliteAdapter.d.ts.map +1 -0
- package/dist/database/SqliteAdapter.js +736 -0
- package/dist/database/SqliteAdapter.js.map +1 -0
- package/dist/filtering/ToolFilter.d.ts +63 -0
- package/dist/filtering/ToolFilter.d.ts.map +1 -0
- package/dist/filtering/ToolFilter.js +242 -0
- package/dist/filtering/ToolFilter.js.map +1 -0
- package/dist/github/GitHubIntegration.d.ts +91 -0
- package/dist/github/GitHubIntegration.d.ts.map +1 -0
- package/dist/github/GitHubIntegration.js +317 -0
- package/dist/github/GitHubIntegration.js.map +1 -0
- package/dist/handlers/prompts/index.d.ts +28 -0
- package/dist/handlers/prompts/index.d.ts.map +1 -0
- package/dist/handlers/prompts/index.js +366 -0
- package/dist/handlers/prompts/index.js.map +1 -0
- package/dist/handlers/resources/index.d.ts +27 -0
- package/dist/handlers/resources/index.d.ts.map +1 -0
- package/dist/handlers/resources/index.js +453 -0
- package/dist/handlers/resources/index.js.map +1 -0
- package/dist/handlers/tools/index.d.ts +26 -0
- package/dist/handlers/tools/index.d.ts.map +1 -0
- package/dist/handlers/tools/index.js +982 -0
- package/dist/handlers/tools/index.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/server/McpServer.d.ts +18 -0
- package/dist/server/McpServer.d.ts.map +1 -0
- package/dist/server/McpServer.js +171 -0
- package/dist/server/McpServer.js.map +1 -0
- package/dist/types/index.d.ts +300 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +15 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/McpLogger.d.ts +61 -0
- package/dist/utils/McpLogger.d.ts.map +1 -0
- package/dist/utils/McpLogger.js +113 -0
- package/dist/utils/McpLogger.js.map +1 -0
- package/dist/utils/logger.d.ts +30 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +70 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/vector/VectorSearchManager.d.ts +63 -0
- package/dist/vector/VectorSearchManager.d.ts.map +1 -0
- package/dist/vector/VectorSearchManager.js +235 -0
- package/dist/vector/VectorSearchManager.js.map +1 -0
- package/docker-compose.yml +37 -0
- package/eslint.config.js +86 -0
- package/mcp-config-example.json +21 -0
- package/package.json +71 -0
- package/releases/release-notes-v2.2.0.md +165 -0
- package/releases/release-notes.md +214 -0
- package/releases/v3.0.0.md +236 -0
- package/server.json +42 -0
- package/src/cli.ts +52 -0
- package/src/constants/ServerInstructions.ts +25 -0
- package/src/database/SqliteAdapter.ts +952 -0
- package/src/filtering/ToolFilter.ts +271 -0
- package/src/github/GitHubIntegration.ts +409 -0
- package/src/handlers/prompts/index.ts +420 -0
- package/src/handlers/resources/index.ts +529 -0
- package/src/handlers/tools/index.ts +1081 -0
- package/src/index.ts +53 -0
- package/src/server/McpServer.ts +230 -0
- package/src/types/index.ts +435 -0
- package/src/types/sql.js.d.ts +34 -0
- package/src/utils/McpLogger.ts +155 -0
- package/src/utils/logger.ts +98 -0
- package/src/vector/VectorSearchManager.ts +277 -0
- package/tools.json +300 -0
- package/tsconfig.json +51 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Journal MCP Server - MCP Protocol Logger
|
|
3
|
+
*
|
|
4
|
+
* Logging that sends structured messages via MCP notifications/message.
|
|
5
|
+
* Falls back to stderr when MCP server is not connected.
|
|
6
|
+
* Follows RFC 5424 severity levels as per MCP spec.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
9
|
+
/**
|
|
10
|
+
* MCP log levels per RFC 5424
|
|
11
|
+
*/
|
|
12
|
+
export type McpLogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical' | 'alert' | 'emergency';
|
|
13
|
+
interface LogData {
|
|
14
|
+
message: string;
|
|
15
|
+
module?: string;
|
|
16
|
+
operation?: string;
|
|
17
|
+
[key: string]: unknown;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* MCP Protocol Logger
|
|
21
|
+
*
|
|
22
|
+
* Sends structured log messages via MCP notifications/message protocol.
|
|
23
|
+
* Falls back to stderr when server not connected.
|
|
24
|
+
*/
|
|
25
|
+
export declare class McpLogger {
|
|
26
|
+
private server;
|
|
27
|
+
private minLevel;
|
|
28
|
+
/**
|
|
29
|
+
* Connect to MCP server for protocol logging
|
|
30
|
+
*/
|
|
31
|
+
setServer(server: McpServer): void;
|
|
32
|
+
/**
|
|
33
|
+
* Set minimum log level (from logging/setLevel request)
|
|
34
|
+
*/
|
|
35
|
+
setLevel(level: McpLogLevel): void;
|
|
36
|
+
/**
|
|
37
|
+
* Get current minimum log level
|
|
38
|
+
*/
|
|
39
|
+
getLevel(): McpLogLevel;
|
|
40
|
+
/**
|
|
41
|
+
* Check if a level should be logged
|
|
42
|
+
*/
|
|
43
|
+
private shouldLog;
|
|
44
|
+
/**
|
|
45
|
+
* Format message for stderr fallback
|
|
46
|
+
*/
|
|
47
|
+
private formatForStderr;
|
|
48
|
+
/**
|
|
49
|
+
* Send log message via MCP protocol or fallback to stderr
|
|
50
|
+
*/
|
|
51
|
+
log(level: McpLogLevel, loggerName: string, data: LogData): void;
|
|
52
|
+
debug(loggerName: string, message: string, context?: Record<string, unknown>): void;
|
|
53
|
+
info(loggerName: string, message: string, context?: Record<string, unknown>): void;
|
|
54
|
+
notice(loggerName: string, message: string, context?: Record<string, unknown>): void;
|
|
55
|
+
warning(loggerName: string, message: string, context?: Record<string, unknown>): void;
|
|
56
|
+
error(loggerName: string, message: string, context?: Record<string, unknown>): void;
|
|
57
|
+
critical(loggerName: string, message: string, context?: Record<string, unknown>): void;
|
|
58
|
+
}
|
|
59
|
+
export declare const mcpLogger: McpLogger;
|
|
60
|
+
export {};
|
|
61
|
+
//# sourceMappingURL=McpLogger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpLogger.d.ts","sourceRoot":"","sources":["../../src/utils/McpLogger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,WAAW,GACjB,OAAO,GACP,MAAM,GACN,QAAQ,GACR,SAAS,GACT,OAAO,GACP,UAAU,GACV,OAAO,GACP,WAAW,CAAC;AAalB,UAAU,OAAO;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED;;;;;GAKG;AACH,qBAAa,SAAS;IAClB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,QAAQ,CAAuB;IAEvC;;OAEG;IACH,SAAS,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAIlC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI;IAMlC;;OAEG;IACH,QAAQ,IAAI,WAAW;IAIvB;;OAEG;IACH,OAAO,CAAC,SAAS;IAIjB;;OAEG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACH,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAsBhE,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAInF,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIlF,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIpF,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIrF,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAInF,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAGzF;AAGD,eAAO,MAAM,SAAS,WAAkB,CAAC"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Journal MCP Server - MCP Protocol Logger
|
|
3
|
+
*
|
|
4
|
+
* Logging that sends structured messages via MCP notifications/message.
|
|
5
|
+
* Falls back to stderr when MCP server is not connected.
|
|
6
|
+
* Follows RFC 5424 severity levels as per MCP spec.
|
|
7
|
+
*/
|
|
8
|
+
const LOG_LEVEL_PRIORITY = {
|
|
9
|
+
emergency: 0,
|
|
10
|
+
alert: 1,
|
|
11
|
+
critical: 2,
|
|
12
|
+
error: 3,
|
|
13
|
+
warning: 4,
|
|
14
|
+
notice: 5,
|
|
15
|
+
info: 6,
|
|
16
|
+
debug: 7,
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* MCP Protocol Logger
|
|
20
|
+
*
|
|
21
|
+
* Sends structured log messages via MCP notifications/message protocol.
|
|
22
|
+
* Falls back to stderr when server not connected.
|
|
23
|
+
*/
|
|
24
|
+
export class McpLogger {
|
|
25
|
+
server = null;
|
|
26
|
+
minLevel = 'info';
|
|
27
|
+
/**
|
|
28
|
+
* Connect to MCP server for protocol logging
|
|
29
|
+
*/
|
|
30
|
+
setServer(server) {
|
|
31
|
+
this.server = server;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Set minimum log level (from logging/setLevel request)
|
|
35
|
+
*/
|
|
36
|
+
setLevel(level) {
|
|
37
|
+
if (level in LOG_LEVEL_PRIORITY) {
|
|
38
|
+
this.minLevel = level;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Get current minimum log level
|
|
43
|
+
*/
|
|
44
|
+
getLevel() {
|
|
45
|
+
return this.minLevel;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Check if a level should be logged
|
|
49
|
+
*/
|
|
50
|
+
shouldLog(level) {
|
|
51
|
+
return LOG_LEVEL_PRIORITY[level] <= LOG_LEVEL_PRIORITY[this.minLevel];
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Format message for stderr fallback
|
|
55
|
+
*/
|
|
56
|
+
formatForStderr(level, loggerName, data) {
|
|
57
|
+
const timestamp = new Date().toISOString();
|
|
58
|
+
const levelUpper = level.toUpperCase().padEnd(9);
|
|
59
|
+
const module = loggerName ? `[${loggerName}]` : '';
|
|
60
|
+
let formatted = `[${timestamp}] [${levelUpper}] ${module} ${data.message}`;
|
|
61
|
+
// Add extra context (filter out message and module)
|
|
62
|
+
const extras = Object.fromEntries(Object.entries(data).filter(([key]) => key !== 'message' && key !== 'module'));
|
|
63
|
+
if (Object.keys(extras).length > 0) {
|
|
64
|
+
formatted += ` ${JSON.stringify(extras)}`;
|
|
65
|
+
}
|
|
66
|
+
return formatted;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Send log message via MCP protocol or fallback to stderr
|
|
70
|
+
*/
|
|
71
|
+
log(level, loggerName, data) {
|
|
72
|
+
if (!this.shouldLog(level))
|
|
73
|
+
return;
|
|
74
|
+
// Send via MCP protocol if server connected
|
|
75
|
+
if (this.server) {
|
|
76
|
+
try {
|
|
77
|
+
void this.server.sendLoggingMessage({
|
|
78
|
+
level,
|
|
79
|
+
logger: loggerName,
|
|
80
|
+
data,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
// Fallback to stderr if MCP send fails
|
|
85
|
+
console.error(this.formatForStderr(level, loggerName, data));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Always also log to stderr for local debugging
|
|
89
|
+
console.error(this.formatForStderr(level, loggerName, data));
|
|
90
|
+
}
|
|
91
|
+
// Convenience methods
|
|
92
|
+
debug(loggerName, message, context) {
|
|
93
|
+
this.log('debug', loggerName, { message, ...context });
|
|
94
|
+
}
|
|
95
|
+
info(loggerName, message, context) {
|
|
96
|
+
this.log('info', loggerName, { message, ...context });
|
|
97
|
+
}
|
|
98
|
+
notice(loggerName, message, context) {
|
|
99
|
+
this.log('notice', loggerName, { message, ...context });
|
|
100
|
+
}
|
|
101
|
+
warning(loggerName, message, context) {
|
|
102
|
+
this.log('warning', loggerName, { message, ...context });
|
|
103
|
+
}
|
|
104
|
+
error(loggerName, message, context) {
|
|
105
|
+
this.log('error', loggerName, { message, ...context });
|
|
106
|
+
}
|
|
107
|
+
critical(loggerName, message, context) {
|
|
108
|
+
this.log('critical', loggerName, { message, ...context });
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Singleton instance
|
|
112
|
+
export const mcpLogger = new McpLogger();
|
|
113
|
+
//# sourceMappingURL=McpLogger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpLogger.js","sourceRoot":"","sources":["../../src/utils/McpLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Journal MCP Server - Logger
|
|
3
|
+
*
|
|
4
|
+
* Centralized logging to stderr only (stdout reserved for MCP protocol).
|
|
5
|
+
* Follows RFC 5424 severity levels.
|
|
6
|
+
*/
|
|
7
|
+
type LogLevel = 'debug' | 'info' | 'notice' | 'warning' | 'error' | 'critical';
|
|
8
|
+
interface LogContext {
|
|
9
|
+
module?: string;
|
|
10
|
+
operation?: string;
|
|
11
|
+
entityId?: string | number;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
}
|
|
14
|
+
declare class Logger {
|
|
15
|
+
private minLevel;
|
|
16
|
+
constructor(level?: LogLevel);
|
|
17
|
+
private shouldLog;
|
|
18
|
+
private formatMessage;
|
|
19
|
+
private log;
|
|
20
|
+
debug(message: string, context?: LogContext): void;
|
|
21
|
+
info(message: string, context?: LogContext): void;
|
|
22
|
+
notice(message: string, context?: LogContext): void;
|
|
23
|
+
warning(message: string, context?: LogContext): void;
|
|
24
|
+
error(message: string, context?: LogContext): void;
|
|
25
|
+
critical(message: string, context?: LogContext): void;
|
|
26
|
+
setLevel(level: LogLevel): void;
|
|
27
|
+
}
|
|
28
|
+
export declare const logger: Logger;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,KAAK,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAE/E,UAAU,UAAU;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAWD,cAAM,MAAM;IACR,OAAO,CAAC,QAAQ,CAAS;gBAEb,KAAK,GAAE,QAAiB;IAIpC,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,GAAG;IASX,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAIlD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAIjD,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAInD,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAIpD,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAIlD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI;IAIrD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;CAGlC;AAKD,eAAO,MAAM,MAAM,QAAuB,CAAC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Journal MCP Server - Logger
|
|
3
|
+
*
|
|
4
|
+
* Centralized logging to stderr only (stdout reserved for MCP protocol).
|
|
5
|
+
* Follows RFC 5424 severity levels.
|
|
6
|
+
*/
|
|
7
|
+
const LOG_LEVELS = {
|
|
8
|
+
debug: 7,
|
|
9
|
+
info: 6,
|
|
10
|
+
notice: 5,
|
|
11
|
+
warning: 4,
|
|
12
|
+
error: 3,
|
|
13
|
+
critical: 2,
|
|
14
|
+
};
|
|
15
|
+
class Logger {
|
|
16
|
+
minLevel;
|
|
17
|
+
constructor(level = 'info') {
|
|
18
|
+
this.minLevel = LOG_LEVELS[level];
|
|
19
|
+
}
|
|
20
|
+
shouldLog(level) {
|
|
21
|
+
return LOG_LEVELS[level] <= this.minLevel;
|
|
22
|
+
}
|
|
23
|
+
formatMessage(level, message, context) {
|
|
24
|
+
const timestamp = new Date().toISOString();
|
|
25
|
+
const levelUpper = level.toUpperCase().padEnd(8);
|
|
26
|
+
const module = context?.module ? `[${context.module}]` : '';
|
|
27
|
+
const operation = context?.operation ? `[${context.operation}]` : '';
|
|
28
|
+
let formatted = `[${timestamp}] [${levelUpper}] ${module}${operation} ${message}`;
|
|
29
|
+
// Add context as JSON if there are additional fields
|
|
30
|
+
const extras = { ...context };
|
|
31
|
+
delete extras.module;
|
|
32
|
+
delete extras.operation;
|
|
33
|
+
if (Object.keys(extras).length > 0) {
|
|
34
|
+
formatted += ` ${JSON.stringify(extras)}`;
|
|
35
|
+
}
|
|
36
|
+
return formatted;
|
|
37
|
+
}
|
|
38
|
+
log(level, message, context) {
|
|
39
|
+
if (!this.shouldLog(level))
|
|
40
|
+
return;
|
|
41
|
+
const formatted = this.formatMessage(level, message, context);
|
|
42
|
+
// Always write to stderr (stdout is reserved for MCP protocol)
|
|
43
|
+
console.error(formatted);
|
|
44
|
+
}
|
|
45
|
+
debug(message, context) {
|
|
46
|
+
this.log('debug', message, context);
|
|
47
|
+
}
|
|
48
|
+
info(message, context) {
|
|
49
|
+
this.log('info', message, context);
|
|
50
|
+
}
|
|
51
|
+
notice(message, context) {
|
|
52
|
+
this.log('notice', message, context);
|
|
53
|
+
}
|
|
54
|
+
warning(message, context) {
|
|
55
|
+
this.log('warning', message, context);
|
|
56
|
+
}
|
|
57
|
+
error(message, context) {
|
|
58
|
+
this.log('error', message, context);
|
|
59
|
+
}
|
|
60
|
+
critical(message, context) {
|
|
61
|
+
this.log('critical', message, context);
|
|
62
|
+
}
|
|
63
|
+
setLevel(level) {
|
|
64
|
+
this.minLevel = LOG_LEVELS[level];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Get log level from environment
|
|
68
|
+
const envLevel = (process.env['LOG_LEVEL'] ?? 'info');
|
|
69
|
+
export const logger = new Logger(envLevel);
|
|
70
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Journal MCP Server - Vector Search Manager
|
|
3
|
+
*
|
|
4
|
+
* Semantic search using @xenova/transformers for embeddings
|
|
5
|
+
* and vectra for vector indexing.
|
|
6
|
+
*/
|
|
7
|
+
import type { SqliteAdapter } from '../database/SqliteAdapter.js';
|
|
8
|
+
import type { JournalEntry } from '../types/index.js';
|
|
9
|
+
/** Search result with similarity score */
|
|
10
|
+
export interface SemanticSearchResult {
|
|
11
|
+
entryId: number;
|
|
12
|
+
score: number;
|
|
13
|
+
entry?: JournalEntry;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* VectorSearchManager - Handles semantic search with local embeddings
|
|
17
|
+
*/
|
|
18
|
+
export declare class VectorSearchManager {
|
|
19
|
+
private embedder;
|
|
20
|
+
private index;
|
|
21
|
+
private readonly indexPath;
|
|
22
|
+
private readonly modelName;
|
|
23
|
+
private initialized;
|
|
24
|
+
private initializing;
|
|
25
|
+
constructor(dbPath: string, modelName?: string);
|
|
26
|
+
/**
|
|
27
|
+
* Check if vector search is initialized
|
|
28
|
+
*/
|
|
29
|
+
isInitialized(): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Initialize the vector search manager (lazy loading)
|
|
32
|
+
*/
|
|
33
|
+
initialize(): Promise<void>;
|
|
34
|
+
/**
|
|
35
|
+
* Generate embedding for text
|
|
36
|
+
*/
|
|
37
|
+
generateEmbedding(text: string): Promise<number[]>;
|
|
38
|
+
/**
|
|
39
|
+
* Add an entry to the vector index (upsert - replaces if exists)
|
|
40
|
+
*/
|
|
41
|
+
addEntry(entryId: number, content: string): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Perform semantic search
|
|
44
|
+
*/
|
|
45
|
+
search(query: string, limit?: number, similarityThreshold?: number): Promise<SemanticSearchResult[]>;
|
|
46
|
+
/**
|
|
47
|
+
* Remove an entry from the vector index
|
|
48
|
+
*/
|
|
49
|
+
removeEntry(entryId: number): Promise<boolean>;
|
|
50
|
+
/**
|
|
51
|
+
* Rebuild index from database entries
|
|
52
|
+
*/
|
|
53
|
+
rebuildIndex(db: SqliteAdapter): Promise<number>;
|
|
54
|
+
/**
|
|
55
|
+
* Get index statistics
|
|
56
|
+
*/
|
|
57
|
+
getStats(): Promise<{
|
|
58
|
+
itemCount: number;
|
|
59
|
+
modelName: string;
|
|
60
|
+
dimensions: number;
|
|
61
|
+
}>;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=VectorSearchManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VectorSearchManager.d.ts","sourceRoot":"","sources":["../../src/vector/VectorSearchManager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAQtD,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,YAAY,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAE5B,OAAO,CAAC,QAAQ,CAAwF;IACxG,OAAO,CAAC,KAAK,CAA2B;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,MAAM,EAAE,SAAS,SAAgB;IAOrD;;OAEG;IACH,aAAa,IAAI,OAAO;IAIxB;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IA2CjC;;OAEG;IACG,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiBxD;;OAEG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA2ClE;;OAEG;IACG,MAAM,CACR,KAAK,EAAE,MAAM,EACb,KAAK,SAAK,EACV,mBAAmB,SAAM,GAC1B,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAmClC;;OAEG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYpD;;OAEG;IACG,YAAY,CAAC,EAAE,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IA+BtD;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;CAgB1F"}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Journal MCP Server - Vector Search Manager
|
|
3
|
+
*
|
|
4
|
+
* Semantic search using @xenova/transformers for embeddings
|
|
5
|
+
* and vectra for vector indexing.
|
|
6
|
+
*/
|
|
7
|
+
import { pipeline } from '@xenova/transformers';
|
|
8
|
+
import { LocalIndex } from 'vectra';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
import * as fs from 'node:fs';
|
|
11
|
+
import { logger } from '../utils/logger.js';
|
|
12
|
+
/** Default model for embeddings (same as Python version) */
|
|
13
|
+
const DEFAULT_MODEL = 'Xenova/all-MiniLM-L6-v2';
|
|
14
|
+
/** Embedding dimensions for all-MiniLM-L6-v2 */
|
|
15
|
+
const EMBEDDING_DIMENSIONS = 384;
|
|
16
|
+
/**
|
|
17
|
+
* VectorSearchManager - Handles semantic search with local embeddings
|
|
18
|
+
*/
|
|
19
|
+
export class VectorSearchManager {
|
|
20
|
+
// Use a more flexible type since FeatureExtractionPipeline doesn't fully implement Pipeline
|
|
21
|
+
embedder = null;
|
|
22
|
+
index = null;
|
|
23
|
+
indexPath;
|
|
24
|
+
modelName;
|
|
25
|
+
initialized = false;
|
|
26
|
+
initializing = false;
|
|
27
|
+
constructor(dbPath, modelName = DEFAULT_MODEL) {
|
|
28
|
+
// Store index in same directory as database
|
|
29
|
+
const dbDir = path.dirname(dbPath);
|
|
30
|
+
this.indexPath = path.join(dbDir, '.vectra_index');
|
|
31
|
+
this.modelName = modelName;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if vector search is initialized
|
|
35
|
+
*/
|
|
36
|
+
isInitialized() {
|
|
37
|
+
return this.initialized;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Initialize the vector search manager (lazy loading)
|
|
41
|
+
*/
|
|
42
|
+
async initialize() {
|
|
43
|
+
if (this.initialized || this.initializing)
|
|
44
|
+
return;
|
|
45
|
+
this.initializing = true;
|
|
46
|
+
try {
|
|
47
|
+
logger.info('Initializing vector search...', { module: 'VectorSearch' });
|
|
48
|
+
// Load embedding model (downloads on first use, ~23MB)
|
|
49
|
+
logger.info(`Loading embedding model: ${this.modelName}`, { module: 'VectorSearch' });
|
|
50
|
+
this.embedder = await pipeline('feature-extraction', this.modelName, {
|
|
51
|
+
quantized: true, // Use quantized model for faster inference
|
|
52
|
+
});
|
|
53
|
+
logger.info('Embedding model loaded', { module: 'VectorSearch' });
|
|
54
|
+
// Create or load vectra index
|
|
55
|
+
if (!fs.existsSync(this.indexPath)) {
|
|
56
|
+
fs.mkdirSync(this.indexPath, { recursive: true });
|
|
57
|
+
}
|
|
58
|
+
this.index = new LocalIndex(this.indexPath);
|
|
59
|
+
// Check if index exists
|
|
60
|
+
if (!await this.index.isIndexCreated()) {
|
|
61
|
+
await this.index.createIndex();
|
|
62
|
+
logger.info('Created new vector index', { module: 'VectorSearch' });
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
logger.info('Loaded existing vector index', { module: 'VectorSearch' });
|
|
66
|
+
}
|
|
67
|
+
this.initialized = true;
|
|
68
|
+
this.initializing = false;
|
|
69
|
+
logger.info('Vector search initialized successfully', { module: 'VectorSearch' });
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
this.initializing = false;
|
|
73
|
+
logger.error('Failed to initialize vector search', {
|
|
74
|
+
module: 'VectorSearch',
|
|
75
|
+
error: error instanceof Error ? error.message : String(error)
|
|
76
|
+
});
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Generate embedding for text
|
|
82
|
+
*/
|
|
83
|
+
async generateEmbedding(text) {
|
|
84
|
+
if (!this.embedder) {
|
|
85
|
+
throw new Error('Vector search not initialized');
|
|
86
|
+
}
|
|
87
|
+
// Generate embedding using feature-extraction pipeline
|
|
88
|
+
// The pipeline returns a Tensor with a data property containing the embeddings
|
|
89
|
+
const output = await this.embedder(text, {
|
|
90
|
+
pooling: 'mean',
|
|
91
|
+
normalize: true,
|
|
92
|
+
});
|
|
93
|
+
// Convert to number array
|
|
94
|
+
const embedding = Array.from(output.data);
|
|
95
|
+
return embedding;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Add an entry to the vector index (upsert - replaces if exists)
|
|
99
|
+
*/
|
|
100
|
+
async addEntry(entryId, content) {
|
|
101
|
+
if (!this.initialized) {
|
|
102
|
+
await this.initialize();
|
|
103
|
+
}
|
|
104
|
+
if (!this.index) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
// Delete existing item first to support upsert behavior
|
|
109
|
+
try {
|
|
110
|
+
await this.index.deleteItem(String(entryId));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// Item may not exist, ignore
|
|
114
|
+
}
|
|
115
|
+
// Generate embedding
|
|
116
|
+
const embedding = await this.generateEmbedding(content);
|
|
117
|
+
// Add to vectra index with entry ID as metadata
|
|
118
|
+
await this.index.insertItem({
|
|
119
|
+
id: String(entryId),
|
|
120
|
+
vector: embedding,
|
|
121
|
+
metadata: { entryId, contentPreview: content.slice(0, 100) }
|
|
122
|
+
});
|
|
123
|
+
logger.debug('Added entry to vector index', {
|
|
124
|
+
module: 'VectorSearch',
|
|
125
|
+
entityId: entryId
|
|
126
|
+
});
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
catch (error) {
|
|
130
|
+
logger.error('Failed to add entry to vector index', {
|
|
131
|
+
module: 'VectorSearch',
|
|
132
|
+
entityId: entryId,
|
|
133
|
+
error: error instanceof Error ? error.message : String(error)
|
|
134
|
+
});
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Perform semantic search
|
|
140
|
+
*/
|
|
141
|
+
async search(query, limit = 10, similarityThreshold = 0.3) {
|
|
142
|
+
if (!this.initialized) {
|
|
143
|
+
await this.initialize();
|
|
144
|
+
}
|
|
145
|
+
if (!this.index) {
|
|
146
|
+
return [];
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
// Generate query embedding
|
|
150
|
+
const queryEmbedding = await this.generateEmbedding(query);
|
|
151
|
+
// Search vectra index
|
|
152
|
+
const results = await this.index.queryItems(queryEmbedding, limit * 2);
|
|
153
|
+
// Filter by threshold and map to our format
|
|
154
|
+
const filteredResults = results
|
|
155
|
+
.filter(r => r.score >= similarityThreshold)
|
|
156
|
+
.slice(0, limit)
|
|
157
|
+
.map(r => ({
|
|
158
|
+
entryId: r.item.metadata.entryId,
|
|
159
|
+
score: r.score
|
|
160
|
+
}));
|
|
161
|
+
return filteredResults;
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
logger.error('Semantic search failed', {
|
|
165
|
+
module: 'VectorSearch',
|
|
166
|
+
error: error instanceof Error ? error.message : String(error)
|
|
167
|
+
});
|
|
168
|
+
return [];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Remove an entry from the vector index
|
|
173
|
+
*/
|
|
174
|
+
async removeEntry(entryId) {
|
|
175
|
+
if (!this.index)
|
|
176
|
+
return false;
|
|
177
|
+
try {
|
|
178
|
+
await this.index.deleteItem(String(entryId));
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
catch {
|
|
182
|
+
// Item might not exist in index
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Rebuild index from database entries
|
|
188
|
+
*/
|
|
189
|
+
async rebuildIndex(db) {
|
|
190
|
+
if (!this.initialized) {
|
|
191
|
+
await this.initialize();
|
|
192
|
+
}
|
|
193
|
+
if (!this.index) {
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
logger.info('Rebuilding vector index from database...', { module: 'VectorSearch' });
|
|
197
|
+
// Get all entries
|
|
198
|
+
const entries = db.getRecentEntries(10000); // Get up to 10k entries
|
|
199
|
+
let indexed = 0;
|
|
200
|
+
for (const entry of entries) {
|
|
201
|
+
// Delete existing item first to avoid "already exists" error
|
|
202
|
+
try {
|
|
203
|
+
await this.index.deleteItem(String(entry.id));
|
|
204
|
+
}
|
|
205
|
+
catch {
|
|
206
|
+
// Item may not exist, ignore
|
|
207
|
+
}
|
|
208
|
+
const success = await this.addEntry(entry.id, entry.content);
|
|
209
|
+
if (success)
|
|
210
|
+
indexed++;
|
|
211
|
+
}
|
|
212
|
+
logger.info(`Rebuilt vector index with ${String(indexed)} entries`, { module: 'VectorSearch' });
|
|
213
|
+
return indexed;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Get index statistics
|
|
217
|
+
*/
|
|
218
|
+
async getStats() {
|
|
219
|
+
if (!this.index) {
|
|
220
|
+
return { itemCount: 0, modelName: this.modelName, dimensions: EMBEDDING_DIMENSIONS };
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const items = await this.index.listItems();
|
|
224
|
+
return {
|
|
225
|
+
itemCount: items.length,
|
|
226
|
+
modelName: this.modelName,
|
|
227
|
+
dimensions: EMBEDDING_DIMENSIONS
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
catch {
|
|
231
|
+
return { itemCount: 0, modelName: this.modelName, dimensions: EMBEDDING_DIMENSIONS };
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=VectorSearchManager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"VectorSearchManager.js","sourceRoot":"","sources":["../../src/vector/VectorSearchManager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
version: '3.8'
|
|
2
|
+
|
|
3
|
+
services:
|
|
4
|
+
memory-journal-mcp:
|
|
5
|
+
build: .
|
|
6
|
+
container_name: memory-journal-mcp
|
|
7
|
+
volumes:
|
|
8
|
+
# Mount local data directory for persistent SQLite database
|
|
9
|
+
- ./data:/app/data
|
|
10
|
+
# Mount git config for context bundle functionality
|
|
11
|
+
- ${HOME}/.gitconfig:/root/.gitconfig:ro
|
|
12
|
+
# Mount SSH keys for GitHub access (optional)
|
|
13
|
+
- ${HOME}/.ssh:/root/.ssh:ro
|
|
14
|
+
environment:
|
|
15
|
+
- DB_PATH=/app/data/memory_journal.db
|
|
16
|
+
- PYTHONPATH=/app
|
|
17
|
+
stdin_open: true
|
|
18
|
+
tty: true
|
|
19
|
+
# For MCP stdio communication
|
|
20
|
+
command: python src/server.py
|
|
21
|
+
restart: unless-stopped
|
|
22
|
+
|
|
23
|
+
# Alternative service for testing without git/ssh mounts
|
|
24
|
+
memory-journal-mcp-basic:
|
|
25
|
+
build: .
|
|
26
|
+
container_name: memory-journal-mcp-basic
|
|
27
|
+
volumes:
|
|
28
|
+
- ./data:/app/data
|
|
29
|
+
environment:
|
|
30
|
+
- DB_PATH=/app/data/memory_journal.db
|
|
31
|
+
- PYTHONPATH=/app
|
|
32
|
+
stdin_open: true
|
|
33
|
+
tty: true
|
|
34
|
+
command: python src/server.py
|
|
35
|
+
restart: unless-stopped
|
|
36
|
+
profiles:
|
|
37
|
+
- basic
|