Skip to content

Commit e37d725

Browse files
authored
Merge branch 'main' into gagik/eslint-type
2 parents 7164709 + af779e1 commit e37d725

File tree

8 files changed

+87
-71
lines changed

8 files changed

+87
-71
lines changed

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
"jest-environment-node": "^29.7.0",
5050
"jest-extended": "^4.0.2",
5151
"mongodb-runner": "^5.8.2",
52-
"native-machine-id": "^0.0.8",
52+
"native-machine-id": "^0.1.0",
5353
"openapi-types": "^12.1.3",
5454
"openapi-typescript": "^7.6.1",
5555
"prettier": "^3.5.3",

src/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ const defaults: UserConfig = {
3131
timeoutMS: 30_000,
3232
},
3333
disabledTools: [],
34+
telemetry: "disabled",
3435
};
3536

3637
export const config = {

src/logger.ts

Lines changed: 66 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export type LogLevel = LoggingMessageNotification["params"]["level"];
88

99
abstract class LoggerBase {
1010
abstract log(level: LogLevel, id: MongoLogId, context: string, message: string): void;
11+
1112
info(id: MongoLogId, context: string, message: string): void {
1213
this.log("info", id, context, message);
1314
}
@@ -47,22 +48,35 @@ class ConsoleLogger extends LoggerBase {
4748
}
4849
}
4950

50-
class Logger extends LoggerBase {
51-
constructor(
52-
private logWriter: MongoLogWriter,
53-
private server: McpServer
54-
) {
51+
class DiskLogger extends LoggerBase {
52+
private constructor(private logWriter: MongoLogWriter) {
5553
super();
5654
}
5755

56+
static async fromPath(logPath: string): Promise<DiskLogger> {
57+
await fs.mkdir(logPath, { recursive: true });
58+
59+
const manager = new MongoLogManager({
60+
directory: logPath,
61+
retentionDays: 30,
62+
onwarn: console.warn,
63+
onerror: console.error,
64+
gzip: false,
65+
retentionGB: 1,
66+
});
67+
68+
await manager.cleanupOldLogFiles();
69+
70+
const logWriter = await manager.createLogWriter();
71+
72+
return new DiskLogger(logWriter);
73+
}
74+
5875
log(level: LogLevel, id: MongoLogId, context: string, message: string): void {
5976
message = redact(message);
6077
const mongoDBLevel = this.mapToMongoDBLogLevel(level);
78+
6179
this.logWriter[mongoDBLevel]("MONGODB-MCP", id, context, message);
62-
void this.server.server.sendLoggingMessage({
63-
level,
64-
data: `[${context}]: ${message}`,
65-
});
6680
}
6781

6882
private mapToMongoDBLogLevel(level: LogLevel): "info" | "warn" | "error" | "debug" | "fatal" {
@@ -86,31 +100,56 @@ class Logger extends LoggerBase {
86100
}
87101
}
88102

89-
class ProxyingLogger extends LoggerBase {
90-
private internalLogger: LoggerBase = new ConsoleLogger();
103+
class McpLogger extends LoggerBase {
104+
constructor(private server: McpServer) {
105+
super();
106+
}
107+
108+
log(level: LogLevel, _: MongoLogId, context: string, message: string): void {
109+
void this.server.server.sendLoggingMessage({
110+
level,
111+
data: `[${context}]: ${message}`,
112+
});
113+
}
114+
}
115+
116+
class CompositeLogger extends LoggerBase {
117+
private loggers: LoggerBase[];
118+
119+
constructor(...loggers: LoggerBase[]) {
120+
super();
121+
122+
if (loggers.length === 0) {
123+
// default to ConsoleLogger
124+
this.loggers = [new ConsoleLogger()];
125+
return;
126+
}
127+
128+
this.loggers = [...loggers];
129+
}
130+
131+
setLoggers(...loggers: LoggerBase[]): void {
132+
if (loggers.length === 0) {
133+
throw new Error("At least one logger must be provided");
134+
}
135+
this.loggers = [...loggers];
136+
}
91137

92138
log(level: LogLevel, id: MongoLogId, context: string, message: string): void {
93-
this.internalLogger.log(level, id, context, message);
139+
for (const logger of this.loggers) {
140+
logger.log(level, id, context, message);
141+
}
94142
}
95143
}
96144

97-
const logger = new ProxyingLogger();
145+
const logger = new CompositeLogger();
98146
export default logger;
99147

100-
export async function initializeLogger(server: McpServer, logPath: string): Promise<void> {
101-
await fs.mkdir(logPath, { recursive: true });
102-
103-
const manager = new MongoLogManager({
104-
directory: logPath,
105-
retentionDays: 30,
106-
onwarn: console.warn,
107-
onerror: console.error,
108-
gzip: false,
109-
retentionGB: 1,
110-
});
148+
export async function initializeLogger(server: McpServer, logPath: string): Promise<LoggerBase> {
149+
const diskLogger = await DiskLogger.fromPath(logPath);
150+
const mcpLogger = new McpLogger(server);
111151

112-
await manager.cleanupOldLogFiles();
152+
logger.setLoggers(mcpLogger, diskLogger);
113153

114-
const logWriter = await manager.createLogWriter();
115-
logger["internalLogger"] = new Logger(logWriter, server);
154+
return logger;
116155
}

src/telemetry/telemetry.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type EventResult = {
1313
};
1414

1515
type CommonProperties = {
16-
device_id: string;
16+
device_id?: string;
1717
mcp_server_version: string;
1818
mcp_server_name: string;
1919
mcp_client_version?: string;

src/telemetry/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface Event {
1414

1515
export interface BaseEvent extends Event {
1616
properties: {
17-
device_id: string;
17+
device_id?: string;
1818
mcp_server_version: string;
1919
mcp_server_name: string;
2020
mcp_client_version?: string;

src/tools/atlas/listProjects.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,16 @@ export class ListProjectsTool extends AtlasToolBase {
1313
};
1414

1515
protected async execute({ orgId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
16+
const orgData = await this.session.apiClient.listOrganizations();
17+
18+
if (!orgData?.results?.length) {
19+
throw new Error("No organizations found in your MongoDB Atlas account.");
20+
}
21+
22+
const orgs: Record<string, string> = orgData.results
23+
.map((org) => [org.id || "", org.name])
24+
.reduce((acc, [id, name]) => ({ ...acc, [id]: name }), {});
25+
1626
const data = orgId
1727
? await this.session.apiClient.listOrganizationProjects({
1828
params: {
@@ -31,11 +41,11 @@ export class ListProjectsTool extends AtlasToolBase {
3141
const rows = data.results
3242
.map((project) => {
3343
const createdAt = project.created ? new Date(project.created).toLocaleString() : "N/A";
34-
return `${project.name} | ${project.id} | ${createdAt}`;
44+
return `${project.name} | ${project.id} | ${orgs[project.orgId]} | ${project.orgId} | ${createdAt}`;
3545
})
3646
.join("\n");
37-
const formattedProjects = `Project Name | Project ID | Created At
38-
----------------| ----------------| ----------------
47+
const formattedProjects = `Project Name | Project ID | Organization Name | Organization ID | Created At
48+
----------------| ----------------| ----------------| ----------------| ----------------
3949
${rows}`;
4050
return {
4151
content: [{ type: "text", text: formattedProjects }],

src/types/native-machine-id.d.ts

Lines changed: 0 additions & 34 deletions
This file was deleted.

0 commit comments

Comments
 (0)