Skip to content

Commit 2febc5d

Browse files
committed
refactor: remove type assertions and simplify state setup
1 parent f278e4f commit 2febc5d

File tree

11 files changed

+60
-86
lines changed

11 files changed

+60
-86
lines changed

eslint.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,11 @@ export default defineConfig([
99
{ files: ["src/**/*.ts"], languageOptions: { globals: globals.node } },
1010
tseslint.configs.recommended,
1111
eslintConfigPrettier,
12+
{
13+
files: ["src/**/*.ts"],
14+
rules: {
15+
"@typescript-eslint/no-non-null-assertion": "error",
16+
},
17+
},
1218
globalIgnores(["node_modules", "dist"]),
1319
]);

src/common/atlas/apiClient.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import config from "../../config.js";
22
import createClient, { FetchOptions, Middleware } from "openapi-fetch";
33

44
import { paths, operations } from "./openapi.js";
5+
import { State } from "../../state.js";
56

67
export interface OAuthToken {
78
access_token: string;
@@ -85,6 +86,18 @@ export class ApiClient {
8586
this.client.use(this.errorMiddleware());
8687
}
8788

89+
static fromState(state: State): ApiClient {
90+
return new ApiClient({
91+
token: state.credentials.auth.token,
92+
saveToken: async (token) => {
93+
state.credentials.auth.code = undefined;
94+
state.credentials.auth.token = token;
95+
state.credentials.auth.status = "issued";
96+
await state.persistCredentials();
97+
},
98+
});
99+
}
100+
88101
async storeToken(token: OAuthToken): Promise<OAuthToken> {
89102
this.token = token;
90103

src/index.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2-
import { Server } from "./server.js";
32
import logger from "./logger.js";
43
import { mongoLogId } from "mongodb-log-writer";
4+
import { ApiClient } from "./common/atlas/apiClient.js";
5+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
6+
import config from "./config.js";
7+
import { State } from "./state.js";
8+
import { registerAtlasTools } from "./tools/atlas/tools.js";
9+
import { registerMongoDBTools } from "./tools/mongodb/index.js";
510

611
export async function runServer() {
7-
const server = new Server();
12+
try {
13+
const state = new State();
14+
await state.loadCredentials();
815

9-
const transport = new StdioServerTransport();
10-
await server.connect(transport);
11-
}
16+
const apiClient = ApiClient.fromState(state);
17+
18+
const mcp = new McpServer({
19+
name: "MongoDB Atlas",
20+
version: config.version,
21+
});
22+
23+
mcp.server.registerCapabilities({ logging: {} });
1224

13-
runServer().catch((error) => {
14-
logger.emergency(mongoLogId(1_000_004), "server", `Fatal error running server: ${error}`);
25+
const transport = new StdioServerTransport();
26+
await mcp.server.connect(transport);
27+
28+
registerAtlasTools(mcp, state, apiClient);
29+
registerMongoDBTools(mcp, state);
30+
} catch (error) {
31+
logger.emergency(mongoLogId(1_000_004), "server", `Fatal error running server: ${error}`);
32+
33+
process.exit(1);
34+
}
35+
}
1536

16-
process.exit(1);
17-
});
37+
runServer();

src/server.ts

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

src/state.ts

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,3 @@ export class State {
4040
}
4141
}
4242
}
43-
44-
const defaultState = new State();
45-
export default defaultState;

src/tools/atlas/createDBUser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export class CreateDBUserTool extends AtlasToolBase {
5353
: undefined,
5454
} as CloudDatabaseUser;
5555

56-
await this.apiClient!.createDatabaseUser({
56+
await this.apiClient.createDatabaseUser({
5757
params: {
5858
path: {
5959
groupId: projectId,

src/tools/atlas/listClusters.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ export class ListClustersTool extends AtlasToolBase {
4747
if (!clusters?.results?.length) {
4848
throw new Error("No clusters found.");
4949
}
50-
const rows = clusters
51-
.results!.map((result) => {
50+
const rows = clusters.results
51+
.map((result) => {
5252
return (result.clusters || []).map((cluster) => {
5353
return { ...result, ...cluster, clusters: undefined };
5454
});
@@ -75,8 +75,8 @@ ${rows}`,
7575
if (!clusters?.results?.length) {
7676
throw new Error("No clusters found.");
7777
}
78-
const rows = clusters
79-
.results!.map((cluster) => {
78+
const rows = clusters.results
79+
.map((cluster) => {
8080
const connectionString = cluster.connectionStrings?.standard || "N/A";
8181
const mongoDBVersion = cluster.mongoDBVersion || "N/A";
8282
return `${cluster.name} | ${cluster.stateName} | ${mongoDBVersion} | ${connectionString}`;

src/tools/atlas/listDBUsers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export class ListDBUsersTool extends AtlasToolBase {
1414
protected async execute({ projectId }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
1515
await this.ensureAuthenticated();
1616

17-
const data = await this.apiClient!.listDatabaseUsers({
17+
const data = await this.apiClient.listDatabaseUsers({
1818
params: {
1919
path: {
2020
groupId: projectId,

src/tools/atlas/listProjects.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ export class ListProjectsTool extends AtlasToolBase {
99
protected async execute(): Promise<CallToolResult> {
1010
await this.ensureAuthenticated();
1111

12-
const data = await this.apiClient!.listProjects();
12+
const data = await this.apiClient.listProjects();
1313

1414
if (!data?.results?.length) {
1515
throw new Error("No projects found in your MongoDB Atlas account.");
1616
}
1717

1818
// Format projects as a table
19-
const rows = data!
20-
.results!.map((project) => {
19+
const rows = data.results
20+
.map((project) => {
2121
const createdAt = project.created ? new Date(project.created).toLocaleString() : "N/A";
2222
return `${project.name} | ${project.id} | ${createdAt}`;
2323
})

tests/unit/index.test.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { describe, it } from "@jest/globals";
2-
import { runServer } from "../../src/index";
3-
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio";
2+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
43

54
// mock the StdioServerTransport
65
jest.mock("@modelcontextprotocol/sdk/server/stdio");
@@ -21,7 +20,6 @@ jest.mock("../../src/server.ts", () => {
2120

2221
describe("Server initialization", () => {
2322
it("should create a server instance", async () => {
24-
await runServer();
25-
expect(StdioServerTransport).toHaveBeenCalled();
23+
await expect(StdioServerTransport).toHaveBeenCalled();
2624
});
2725
});

tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"rootDir": "./src",
77
"outDir": "./dist",
88
"strict": true,
9+
"strictNullChecks": true,
910
"esModuleInterop": true,
1011
"types": ["node"],
1112
"sourceMap": true,

0 commit comments

Comments
 (0)