mongodb-mcp-server 0.1.2 → 0.2.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/.github/pull_request_template.md +5 -0
- package/.github/workflows/accuracy-tests.yml +55 -0
- package/.github/workflows/check.yml +1 -1
- package/.github/workflows/code_health.yaml +4 -4
- package/.github/workflows/code_health_fork.yaml +0 -14
- package/.github/workflows/dependabot_pr.yaml +26 -0
- package/.github/workflows/docker.yaml +1 -1
- package/.github/workflows/jira-issue.yml +72 -0
- package/.smithery/smithery.yaml +10 -0
- package/.vscode/extensions.json +1 -1
- package/.vscode/launch.json +11 -1
- package/.vscode/settings.json +1 -11
- package/Dockerfile +1 -0
- package/README.md +132 -31
- package/dist/common/atlas/accessListUtils.js +36 -0
- package/dist/common/atlas/accessListUtils.js.map +1 -0
- package/dist/common/atlas/apiClient.js +25 -6
- package/dist/common/atlas/apiClient.js.map +1 -1
- package/dist/common/atlas/cluster.js +1 -1
- package/dist/common/atlas/cluster.js.map +1 -1
- package/dist/{config.js → common/config.js} +8 -1
- package/dist/common/config.js.map +1 -0
- package/dist/{errors.js → common/errors.js} +1 -0
- package/dist/common/errors.js.map +1 -0
- package/dist/{logger.js → common/logger.js} +20 -19
- package/dist/common/logger.js.map +1 -0
- package/dist/common/managedTimeout.js +20 -0
- package/dist/common/managedTimeout.js.map +1 -0
- package/dist/common/packageInfo.js.map +1 -0
- package/dist/{session.js → common/session.js} +20 -21
- package/dist/common/session.js.map +1 -0
- package/dist/common/sessionStore.js +73 -0
- package/dist/common/sessionStore.js.map +1 -0
- package/dist/helpers/container.js +28 -0
- package/dist/helpers/container.js.map +1 -0
- package/dist/helpers/generatePassword.js.map +1 -0
- package/dist/helpers/indexCheck.js +63 -0
- package/dist/helpers/indexCheck.js.map +1 -0
- package/dist/index.js +30 -37
- package/dist/index.js.map +1 -1
- package/dist/server.js +44 -7
- package/dist/server.js.map +1 -1
- package/dist/telemetry/constants.js +1 -1
- package/dist/telemetry/constants.js.map +1 -1
- package/dist/telemetry/telemetry.js +86 -116
- package/dist/telemetry/telemetry.js.map +1 -1
- package/dist/tools/atlas/atlasTool.js +3 -3
- package/dist/tools/atlas/atlasTool.js.map +1 -1
- package/dist/tools/atlas/connect/connectCluster.js +198 -0
- package/dist/tools/atlas/connect/connectCluster.js.map +1 -0
- package/dist/tools/atlas/create/createAccessList.js +9 -10
- package/dist/tools/atlas/create/createAccessList.js.map +1 -1
- package/dist/tools/atlas/create/createDBUser.js +3 -1
- package/dist/tools/atlas/create/createDBUser.js.map +1 -1
- package/dist/tools/atlas/create/createFreeCluster.js +2 -0
- package/dist/tools/atlas/create/createFreeCluster.js.map +1 -1
- package/dist/tools/atlas/create/createProject.js.map +1 -1
- package/dist/tools/atlas/read/inspectAccessList.js.map +1 -1
- package/dist/tools/atlas/read/inspectCluster.js.map +1 -1
- package/dist/tools/atlas/read/listAlerts.js.map +1 -1
- package/dist/tools/atlas/read/listClusters.js.map +1 -1
- package/dist/tools/atlas/read/listDBUsers.js.map +1 -1
- package/dist/tools/atlas/read/listOrgs.js.map +1 -1
- package/dist/tools/atlas/read/listProjects.js.map +1 -1
- package/dist/tools/atlas/tools.js +1 -1
- package/dist/tools/atlas/tools.js.map +1 -1
- package/dist/tools/mongodb/{metadata → connect}/connect.js +7 -4
- package/dist/tools/mongodb/connect/connect.js.map +1 -0
- package/dist/tools/mongodb/create/createCollection.js.map +1 -1
- package/dist/tools/mongodb/create/createIndex.js +1 -1
- package/dist/tools/mongodb/create/createIndex.js.map +1 -1
- package/dist/tools/mongodb/create/insertMany.js +1 -1
- package/dist/tools/mongodb/create/insertMany.js.map +1 -1
- package/dist/tools/mongodb/delete/deleteMany.js +20 -1
- package/dist/tools/mongodb/delete/deleteMany.js.map +1 -1
- package/dist/tools/mongodb/delete/dropCollection.js.map +1 -1
- package/dist/tools/mongodb/delete/dropDatabase.js.map +1 -1
- package/dist/tools/mongodb/metadata/collectionSchema.js.map +1 -1
- package/dist/tools/mongodb/metadata/collectionStorageSize.js.map +1 -1
- package/dist/tools/mongodb/metadata/dbStats.js.map +1 -1
- package/dist/tools/mongodb/metadata/explain.js +2 -2
- package/dist/tools/mongodb/metadata/explain.js.map +1 -1
- package/dist/tools/mongodb/metadata/listCollections.js.map +1 -1
- package/dist/tools/mongodb/metadata/listDatabases.js.map +1 -1
- package/dist/tools/mongodb/metadata/logs.js.map +1 -1
- package/dist/tools/mongodb/mongodbTool.js +47 -10
- package/dist/tools/mongodb/mongodbTool.js.map +1 -1
- package/dist/tools/mongodb/read/aggregate.js +10 -1
- package/dist/tools/mongodb/read/aggregate.js.map +1 -1
- package/dist/tools/mongodb/read/collectionIndexes.js.map +1 -1
- package/dist/tools/mongodb/read/count.js +15 -1
- package/dist/tools/mongodb/read/count.js.map +1 -1
- package/dist/tools/mongodb/read/find.js +14 -4
- package/dist/tools/mongodb/read/find.js.map +1 -1
- package/dist/tools/mongodb/tools.js +1 -1
- package/dist/tools/mongodb/tools.js.map +1 -1
- package/dist/tools/mongodb/update/renameCollection.js.map +1 -1
- package/dist/tools/mongodb/update/updateMany.js +24 -2
- package/dist/tools/mongodb/update/updateMany.js.map +1 -1
- package/dist/tools/tool.js +12 -9
- package/dist/tools/tool.js.map +1 -1
- package/dist/transports/base.js +26 -0
- package/dist/transports/base.js.map +1 -0
- package/dist/{helpers/EJsonTransport.js → transports/stdio.js} +24 -2
- package/dist/transports/stdio.js.map +1 -0
- package/dist/transports/streamableHttp.js +140 -0
- package/dist/transports/streamableHttp.js.map +1 -0
- package/eslint.config.js +13 -4
- package/package.json +43 -33
- package/resources/test-summary-template.html +415 -0
- package/scripts/accuracy/generateTestSummary.ts +335 -0
- package/scripts/accuracy/runAccuracyTests.sh +45 -0
- package/scripts/accuracy/updateAccuracyRunStatus.ts +21 -0
- package/src/common/atlas/accessListUtils.ts +54 -0
- package/src/common/atlas/apiClient.ts +25 -6
- package/src/common/atlas/cluster.ts +1 -1
- package/src/{config.ts → common/config.ts} +16 -2
- package/src/{errors.ts → common/errors.ts} +1 -0
- package/src/{logger.ts → common/logger.ts} +21 -24
- package/src/common/managedTimeout.ts +27 -0
- package/src/{session.ts → common/session.ts} +24 -26
- package/src/common/sessionStore.ts +111 -0
- package/src/helpers/container.ts +35 -0
- package/src/helpers/indexCheck.ts +83 -0
- package/src/index.ts +30 -40
- package/src/server.ts +55 -11
- package/src/telemetry/constants.ts +1 -1
- package/src/telemetry/telemetry.ts +109 -153
- package/src/telemetry/types.ts +2 -1
- package/src/tools/atlas/atlasTool.ts +4 -4
- package/src/tools/atlas/connect/connectCluster.ts +259 -0
- package/src/tools/atlas/create/createAccessList.ts +15 -13
- package/src/tools/atlas/create/createDBUser.ts +5 -3
- package/src/tools/atlas/create/createFreeCluster.ts +4 -2
- package/src/tools/atlas/create/createProject.ts +2 -2
- package/src/tools/atlas/read/inspectAccessList.ts +2 -2
- package/src/tools/atlas/read/inspectCluster.ts +2 -2
- package/src/tools/atlas/read/listAlerts.ts +2 -2
- package/src/tools/atlas/read/listClusters.ts +2 -2
- package/src/tools/atlas/read/listDBUsers.ts +2 -2
- package/src/tools/atlas/read/listOrgs.ts +2 -2
- package/src/tools/atlas/read/listProjects.ts +2 -2
- package/src/tools/atlas/tools.ts +1 -1
- package/src/tools/mongodb/{metadata → connect}/connect.ts +12 -9
- package/src/tools/mongodb/create/createCollection.ts +2 -2
- package/src/tools/mongodb/create/createIndex.ts +3 -3
- package/src/tools/mongodb/create/insertMany.ts +3 -3
- package/src/tools/mongodb/delete/deleteMany.ts +24 -3
- package/src/tools/mongodb/delete/dropCollection.ts +2 -2
- package/src/tools/mongodb/delete/dropDatabase.ts +2 -2
- package/src/tools/mongodb/metadata/collectionSchema.ts +2 -2
- package/src/tools/mongodb/metadata/collectionStorageSize.ts +2 -2
- package/src/tools/mongodb/metadata/dbStats.ts +2 -2
- package/src/tools/mongodb/metadata/explain.ts +4 -4
- package/src/tools/mongodb/metadata/listCollections.ts +2 -2
- package/src/tools/mongodb/metadata/listDatabases.ts +2 -2
- package/src/tools/mongodb/metadata/logs.ts +2 -2
- package/src/tools/mongodb/mongodbTool.ts +60 -14
- package/src/tools/mongodb/read/aggregate.ts +14 -3
- package/src/tools/mongodb/read/collectionIndexes.ts +2 -2
- package/src/tools/mongodb/read/count.ts +19 -3
- package/src/tools/mongodb/read/find.ts +20 -6
- package/src/tools/mongodb/tools.ts +1 -1
- package/src/tools/mongodb/update/renameCollection.ts +2 -2
- package/src/tools/mongodb/update/updateMany.ts +28 -4
- package/src/tools/tool.ts +23 -18
- package/src/transports/base.ts +34 -0
- package/src/{helpers/EJsonTransport.ts → transports/stdio.ts} +30 -1
- package/src/transports/streamableHttp.ts +178 -0
- package/tests/accuracy/aggregate.test.ts +27 -0
- package/tests/accuracy/collectionIndexes.test.ts +40 -0
- package/tests/accuracy/collectionSchema.test.ts +28 -0
- package/tests/accuracy/collectionStorageSize.test.ts +41 -0
- package/tests/accuracy/count.test.ts +44 -0
- package/tests/accuracy/createCollection.test.ts +46 -0
- package/tests/accuracy/createIndex.test.ts +37 -0
- package/tests/accuracy/dbStats.test.ts +15 -0
- package/tests/accuracy/deleteMany.test.ts +44 -0
- package/tests/accuracy/dropCollection.test.ts +74 -0
- package/tests/accuracy/dropDatabase.test.ts +41 -0
- package/tests/accuracy/explain.test.ts +73 -0
- package/tests/accuracy/find.test.ts +114 -0
- package/tests/accuracy/insertMany.test.ts +48 -0
- package/tests/accuracy/listCollections.test.ts +60 -0
- package/tests/accuracy/listDatabases.test.ts +31 -0
- package/tests/accuracy/logs.test.ts +28 -0
- package/tests/accuracy/renameCollection.test.ts +31 -0
- package/tests/accuracy/sdk/accuracyResultStorage/diskStorage.ts +189 -0
- package/tests/accuracy/sdk/accuracyResultStorage/getAccuracyResultStorage.ts +11 -0
- package/tests/accuracy/sdk/accuracyResultStorage/mongodbStorage.ts +151 -0
- package/tests/accuracy/sdk/accuracyResultStorage/resultStorage.ts +117 -0
- package/tests/accuracy/sdk/accuracyScorer.ts +93 -0
- package/tests/accuracy/sdk/accuracyTestingClient.ts +94 -0
- package/tests/accuracy/sdk/agent.ts +56 -0
- package/tests/accuracy/sdk/constants.ts +26 -0
- package/tests/accuracy/sdk/describeAccuracyTests.ts +126 -0
- package/tests/accuracy/sdk/gitInfo.ts +7 -0
- package/tests/accuracy/sdk/matcher.ts +193 -0
- package/tests/accuracy/sdk/models.ts +95 -0
- package/tests/accuracy/test-data-dumps/comics.books.json +417 -0
- package/tests/accuracy/test-data-dumps/comics.characters.json +402 -0
- package/tests/accuracy/test-data-dumps/mflix.movies.json +496 -0
- package/tests/accuracy/test-data-dumps/mflix.shows.json +572 -0
- package/tests/accuracy/updateMany.test.ts +42 -0
- package/tests/integration/helpers.ts +9 -9
- package/tests/integration/indexCheck.test.ts +464 -0
- package/tests/integration/server.test.ts +6 -4
- package/tests/integration/telemetry.test.ts +29 -0
- package/tests/integration/tools/atlas/accessLists.test.ts +22 -2
- package/tests/integration/tools/atlas/alerts.test.ts +3 -2
- package/tests/integration/tools/atlas/atlasHelpers.ts +3 -0
- package/tests/integration/tools/atlas/clusters.test.ts +68 -16
- package/tests/integration/tools/atlas/dbUsers.test.ts +14 -1
- package/tests/integration/tools/atlas/orgs.test.ts +2 -1
- package/tests/integration/tools/atlas/projects.test.ts +4 -3
- package/tests/integration/tools/mongodb/{metadata → connect}/connect.test.ts +34 -3
- package/tests/integration/tools/mongodb/create/createCollection.test.ts +1 -0
- package/tests/integration/tools/mongodb/create/createIndex.test.ts +1 -0
- package/tests/integration/tools/mongodb/create/insertMany.test.ts +1 -0
- package/tests/integration/tools/mongodb/delete/deleteMany.test.ts +1 -0
- package/tests/integration/tools/mongodb/delete/dropCollection.test.ts +1 -1
- package/tests/integration/tools/mongodb/delete/dropDatabase.test.ts +1 -0
- package/tests/integration/tools/mongodb/metadata/collectionSchema.test.ts +1 -0
- package/tests/integration/tools/mongodb/metadata/collectionStorageSize.test.ts +1 -0
- package/tests/integration/tools/mongodb/metadata/dbStats.test.ts +1 -0
- package/tests/integration/tools/mongodb/metadata/explain.test.ts +1 -0
- package/tests/integration/tools/mongodb/metadata/listCollections.test.ts +1 -0
- package/tests/integration/tools/mongodb/metadata/listDatabases.test.ts +3 -2
- package/tests/integration/tools/mongodb/metadata/logs.test.ts +1 -0
- package/tests/integration/tools/mongodb/mongodbHelpers.ts +67 -2
- package/tests/integration/tools/mongodb/read/aggregate.test.ts +2 -1
- package/tests/integration/tools/mongodb/read/collectionIndexes.test.ts +1 -0
- package/tests/integration/tools/mongodb/read/count.test.ts +1 -0
- package/tests/integration/tools/mongodb/read/find.test.ts +2 -1
- package/tests/integration/tools/mongodb/update/renameCollection.test.ts +1 -0
- package/tests/integration/tools/mongodb/update/updateMany.test.ts +1 -0
- package/tests/integration/transports/stdio.test.ts +40 -0
- package/tests/integration/transports/streamableHttp.test.ts +56 -0
- package/tests/matchers/toIncludeSameMembers.test.ts +59 -0
- package/tests/matchers/toIncludeSameMembers.ts +12 -0
- package/tests/setup.ts +7 -0
- package/tests/unit/accessListUtils.test.ts +39 -0
- package/tests/unit/accuracyScorer.test.ts +390 -0
- package/tests/unit/{apiClient.test.ts → common/apiClient.test.ts} +15 -15
- package/tests/unit/common/managedTimeout.test.ts +67 -0
- package/tests/unit/{session.test.ts → common/session.test.ts} +7 -12
- package/tests/unit/helpers/indexCheck.test.ts +150 -0
- package/tests/unit/telemetry.test.ts +99 -137
- package/tests/unit/{EJsonTransport.test.ts → transports/stdio.test.ts} +4 -4
- package/tests/vitest.d.ts +11 -0
- package/tsconfig.json +0 -1
- package/{tsconfig.jest.json → tsconfig.test.json} +1 -2
- package/vitest.config.ts +41 -0
- package/dist/common/atlas/generatePassword.js.map +0 -1
- package/dist/config.js.map +0 -1
- package/dist/errors.js.map +0 -1
- package/dist/helpers/EJsonTransport.js.map +0 -1
- package/dist/helpers/packageInfo.js.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/session.js.map +0 -1
- package/dist/tools/atlas/metadata/connectCluster.js +0 -100
- package/dist/tools/atlas/metadata/connectCluster.js.map +0 -1
- package/dist/tools/mongodb/metadata/connect.js.map +0 -1
- package/global.d.ts +0 -1
- package/jest.config.cjs +0 -22
- package/src/tools/atlas/metadata/connectCluster.ts +0 -121
- /package/dist/{helpers → common}/packageInfo.js +0 -0
- /package/dist/{common/atlas → helpers}/generatePassword.js +0 -0
- /package/src/{helpers → common}/packageInfo.ts +0 -0
- /package/src/{common/atlas → helpers}/generatePassword.ts +0 -0
|
@@ -2,8 +2,9 @@ import { z } from "zod";
|
|
|
2
2
|
import { ToolArgs, ToolBase, ToolCategory, TelemetryToolMetadata } from "../tool.js";
|
|
3
3
|
import { NodeDriverServiceProvider } from "@mongosh/service-provider-node-driver";
|
|
4
4
|
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
5
|
-
import { ErrorCodes, MongoDBError } from "../../errors.js";
|
|
6
|
-
import logger, { LogId } from "../../logger.js";
|
|
5
|
+
import { ErrorCodes, MongoDBError } from "../../common/errors.js";
|
|
6
|
+
import logger, { LogId } from "../../common/logger.js";
|
|
7
|
+
import { Server } from "../../server.js";
|
|
7
8
|
|
|
8
9
|
export const DbOperationArgs = {
|
|
9
10
|
database: z.string().describe("Database name"),
|
|
@@ -11,19 +12,29 @@ export const DbOperationArgs = {
|
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
export abstract class MongoDBToolBase extends ToolBase {
|
|
14
|
-
|
|
15
|
+
private server?: Server;
|
|
16
|
+
public category: ToolCategory = "mongodb";
|
|
15
17
|
|
|
16
18
|
protected async ensureConnected(): Promise<NodeDriverServiceProvider> {
|
|
17
|
-
if (!this.session.serviceProvider
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
LogId.mongodbConnectFailure,
|
|
23
|
-
"mongodbTool",
|
|
24
|
-
`Failed to connect to MongoDB instance using the connection string from the config: ${error as string}`
|
|
19
|
+
if (!this.session.serviceProvider) {
|
|
20
|
+
if (this.session.connectedAtlasCluster) {
|
|
21
|
+
throw new MongoDBError(
|
|
22
|
+
ErrorCodes.NotConnectedToMongoDB,
|
|
23
|
+
`Attempting to connect to Atlas cluster "${this.session.connectedAtlasCluster.clusterName}", try again in a few seconds.`
|
|
25
24
|
);
|
|
26
|
-
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (this.config.connectionString) {
|
|
28
|
+
try {
|
|
29
|
+
await this.connectToMongoDB(this.config.connectionString);
|
|
30
|
+
} catch (error) {
|
|
31
|
+
logger.error(
|
|
32
|
+
LogId.mongodbConnectFailure,
|
|
33
|
+
"mongodbTool",
|
|
34
|
+
`Failed to connect to MongoDB instance using the connection string from the config: ${error as string}`
|
|
35
|
+
);
|
|
36
|
+
throw new MongoDBError(ErrorCodes.MisconfiguredConnectionString, "Not connected to MongoDB.");
|
|
37
|
+
}
|
|
27
38
|
}
|
|
28
39
|
}
|
|
29
40
|
|
|
@@ -34,11 +45,28 @@ export abstract class MongoDBToolBase extends ToolBase {
|
|
|
34
45
|
return this.session.serviceProvider;
|
|
35
46
|
}
|
|
36
47
|
|
|
48
|
+
public register(server: Server): boolean {
|
|
49
|
+
this.server = server;
|
|
50
|
+
return super.register(server);
|
|
51
|
+
}
|
|
52
|
+
|
|
37
53
|
protected handleError(
|
|
38
54
|
error: unknown,
|
|
39
55
|
args: ToolArgs<typeof this.argsShape>
|
|
40
56
|
): Promise<CallToolResult> | CallToolResult {
|
|
41
57
|
if (error instanceof MongoDBError) {
|
|
58
|
+
const connectTools = this.server?.tools
|
|
59
|
+
.filter((t) => t.operationType === "connect")
|
|
60
|
+
.sort((a, b) => a.category.localeCompare(b.category)); // Sort Altas tools before MongoDB tools
|
|
61
|
+
|
|
62
|
+
// Find the first Atlas connect tool if available and suggest to the LLM to use it.
|
|
63
|
+
// Note: if we ever have multiple Atlas connect tools, we may want to refine this logic to select the most appropriate one.
|
|
64
|
+
const atlasConnectTool = connectTools?.find((t) => t.category === "atlas");
|
|
65
|
+
const llmConnectHint = atlasConnectTool
|
|
66
|
+
? `Note to LLM: prefer using the "${atlasConnectTool.name}" tool to connect to an Atlas cluster over using a connection string. Make sure to ask the user to specify a cluster name they want to connect to or ask them if they want to use the "list-clusters" tool to list all their clusters. Do not invent cluster names or connection strings unless the user has explicitly specified them. If they've previously connected to MongoDB using MCP, you can ask them if they want to reconnect using the same cluster/connection.`
|
|
67
|
+
: "Note to LLM: do not invent connection strings and explicitly ask the user to provide one. If they have previously connected to MongoDB using MCP, you can ask them if they want to reconnect using the same connection string.";
|
|
68
|
+
|
|
69
|
+
const connectToolsNames = connectTools?.map((t) => `"${t.name}"`).join(", ");
|
|
42
70
|
switch (error.code) {
|
|
43
71
|
case ErrorCodes.NotConnectedToMongoDB:
|
|
44
72
|
return {
|
|
@@ -49,7 +77,9 @@ export abstract class MongoDBToolBase extends ToolBase {
|
|
|
49
77
|
},
|
|
50
78
|
{
|
|
51
79
|
type: "text",
|
|
52
|
-
text:
|
|
80
|
+
text: connectToolsNames
|
|
81
|
+
? `Please use one of the following tools: ${connectToolsNames} to connect to a MongoDB instance or update the MCP server configuration to include a connection string. ${llmConnectHint}`
|
|
82
|
+
: "There are no tools available to connect. Please update the configuration to include a connection string and restart the server.",
|
|
53
83
|
},
|
|
54
84
|
],
|
|
55
85
|
isError: true,
|
|
@@ -59,7 +89,23 @@ export abstract class MongoDBToolBase extends ToolBase {
|
|
|
59
89
|
content: [
|
|
60
90
|
{
|
|
61
91
|
type: "text",
|
|
62
|
-
text: "The configured connection string is not valid. Please check the connection string and confirm it points to a valid MongoDB instance.
|
|
92
|
+
text: "The configured connection string is not valid. Please check the connection string and confirm it points to a valid MongoDB instance.",
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
type: "text",
|
|
96
|
+
text: connectTools
|
|
97
|
+
? `Alternatively, you can use one of the following tools: ${connectToolsNames} to connect to a MongoDB instance. ${llmConnectHint}`
|
|
98
|
+
: "Please update the configuration to use a valid connection string and restart the server.",
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
isError: true,
|
|
102
|
+
};
|
|
103
|
+
case ErrorCodes.ForbiddenCollscan:
|
|
104
|
+
return {
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: "text",
|
|
108
|
+
text: error.message,
|
|
63
109
|
},
|
|
64
110
|
],
|
|
65
111
|
isError: true,
|
|
@@ -3,19 +3,20 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
|
3
3
|
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
4
4
|
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
5
|
import { EJSON } from "bson";
|
|
6
|
+
import { checkIndexUsage } from "../../../helpers/indexCheck.js";
|
|
6
7
|
|
|
7
8
|
export const AggregateArgs = {
|
|
8
|
-
pipeline: z.array(z.
|
|
9
|
+
pipeline: z.array(z.object({}).passthrough()).describe("An array of aggregation stages to execute"),
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
export class AggregateTool extends MongoDBToolBase {
|
|
12
|
-
|
|
13
|
+
public name = "aggregate";
|
|
13
14
|
protected description = "Run an aggregation against a MongoDB collection";
|
|
14
15
|
protected argsShape = {
|
|
15
16
|
...DbOperationArgs,
|
|
16
17
|
...AggregateArgs,
|
|
17
18
|
};
|
|
18
|
-
|
|
19
|
+
public operationType: OperationType = "read";
|
|
19
20
|
|
|
20
21
|
protected async execute({
|
|
21
22
|
database,
|
|
@@ -23,6 +24,16 @@ export class AggregateTool extends MongoDBToolBase {
|
|
|
23
24
|
pipeline,
|
|
24
25
|
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
25
26
|
const provider = await this.ensureConnected();
|
|
27
|
+
|
|
28
|
+
// Check if aggregate operation uses an index if enabled
|
|
29
|
+
if (this.config.indexCheck) {
|
|
30
|
+
await checkIndexUsage(provider, database, collection, "aggregate", async () => {
|
|
31
|
+
return provider
|
|
32
|
+
.aggregate(database, collection, pipeline, {}, { writeConcern: undefined })
|
|
33
|
+
.explain("queryPlanner");
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
26
37
|
const documents = await provider.aggregate(database, collection, pipeline).toArray();
|
|
27
38
|
|
|
28
39
|
const content: Array<{ text: string; type: "text" }> = [
|
|
@@ -3,10 +3,10 @@ import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
|
3
3
|
import { ToolArgs, OperationType } from "../../tool.js";
|
|
4
4
|
|
|
5
5
|
export class CollectionIndexesTool extends MongoDBToolBase {
|
|
6
|
-
|
|
6
|
+
public name = "collection-indexes";
|
|
7
7
|
protected description = "Describe the indexes for a collection";
|
|
8
8
|
protected argsShape = DbOperationArgs;
|
|
9
|
-
|
|
9
|
+
public operationType: OperationType = "read";
|
|
10
10
|
|
|
11
11
|
protected async execute({ database, collection }: ToolArgs<typeof DbOperationArgs>): Promise<CallToolResult> {
|
|
12
12
|
const provider = await this.ensureConnected();
|
|
@@ -2,10 +2,12 @@ import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
|
2
2
|
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
3
3
|
import { ToolArgs, OperationType } from "../../tool.js";
|
|
4
4
|
import { z } from "zod";
|
|
5
|
+
import { checkIndexUsage } from "../../../helpers/indexCheck.js";
|
|
5
6
|
|
|
6
7
|
export const CountArgs = {
|
|
7
8
|
query: z
|
|
8
|
-
.
|
|
9
|
+
.object({})
|
|
10
|
+
.passthrough()
|
|
9
11
|
.optional()
|
|
10
12
|
.describe(
|
|
11
13
|
"A filter/query parameter. Allows users to filter the documents to count. Matches the syntax of the filter argument of db.collection.count()."
|
|
@@ -13,7 +15,7 @@ export const CountArgs = {
|
|
|
13
15
|
};
|
|
14
16
|
|
|
15
17
|
export class CountTool extends MongoDBToolBase {
|
|
16
|
-
|
|
18
|
+
public name = "count";
|
|
17
19
|
protected description =
|
|
18
20
|
"Gets the number of documents in a MongoDB collection using db.collection.count() and query as an optional filter parameter";
|
|
19
21
|
protected argsShape = {
|
|
@@ -21,10 +23,24 @@ export class CountTool extends MongoDBToolBase {
|
|
|
21
23
|
...CountArgs,
|
|
22
24
|
};
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
public operationType: OperationType = "read";
|
|
25
27
|
|
|
26
28
|
protected async execute({ database, collection, query }: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
27
29
|
const provider = await this.ensureConnected();
|
|
30
|
+
|
|
31
|
+
// Check if count operation uses an index if enabled
|
|
32
|
+
if (this.config.indexCheck) {
|
|
33
|
+
await checkIndexUsage(provider, database, collection, "count", async () => {
|
|
34
|
+
return provider.runCommandWithCheck(database, {
|
|
35
|
+
explain: {
|
|
36
|
+
count: collection,
|
|
37
|
+
query,
|
|
38
|
+
},
|
|
39
|
+
verbosity: "queryPlanner",
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
|
|
28
44
|
const count = await provider.count(database, collection, query);
|
|
29
45
|
|
|
30
46
|
return {
|
|
@@ -4,31 +4,37 @@ import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
|
4
4
|
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
5
|
import { SortDirection } from "mongodb";
|
|
6
6
|
import { EJSON } from "bson";
|
|
7
|
+
import { checkIndexUsage } from "../../../helpers/indexCheck.js";
|
|
7
8
|
|
|
8
9
|
export const FindArgs = {
|
|
9
10
|
filter: z
|
|
10
|
-
.
|
|
11
|
+
.object({})
|
|
12
|
+
.passthrough()
|
|
11
13
|
.optional()
|
|
12
14
|
.describe("The query filter, matching the syntax of the query argument of db.collection.find()"),
|
|
13
15
|
projection: z
|
|
14
|
-
.
|
|
16
|
+
.object({})
|
|
17
|
+
.passthrough()
|
|
15
18
|
.optional()
|
|
16
19
|
.describe("The projection, matching the syntax of the projection argument of db.collection.find()"),
|
|
17
20
|
limit: z.number().optional().default(10).describe("The maximum number of documents to return"),
|
|
18
21
|
sort: z
|
|
19
|
-
.
|
|
22
|
+
.object({})
|
|
23
|
+
.catchall(z.custom<SortDirection>())
|
|
20
24
|
.optional()
|
|
21
|
-
.describe(
|
|
25
|
+
.describe(
|
|
26
|
+
"A document, describing the sort order, matching the syntax of the sort argument of cursor.sort(). The keys of the object are the fields to sort on, while the values are the sort directions (1 for ascending, -1 for descending)."
|
|
27
|
+
),
|
|
22
28
|
};
|
|
23
29
|
|
|
24
30
|
export class FindTool extends MongoDBToolBase {
|
|
25
|
-
|
|
31
|
+
public name = "find";
|
|
26
32
|
protected description = "Run a find query against a MongoDB collection";
|
|
27
33
|
protected argsShape = {
|
|
28
34
|
...DbOperationArgs,
|
|
29
35
|
...FindArgs,
|
|
30
36
|
};
|
|
31
|
-
|
|
37
|
+
public operationType: OperationType = "read";
|
|
32
38
|
|
|
33
39
|
protected async execute({
|
|
34
40
|
database,
|
|
@@ -39,6 +45,14 @@ export class FindTool extends MongoDBToolBase {
|
|
|
39
45
|
sort,
|
|
40
46
|
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
41
47
|
const provider = await this.ensureConnected();
|
|
48
|
+
|
|
49
|
+
// Check if find operation uses an index if enabled
|
|
50
|
+
if (this.config.indexCheck) {
|
|
51
|
+
await checkIndexUsage(provider, database, collection, "find", async () => {
|
|
52
|
+
return provider.find(database, collection, filter, { projection, limit, sort }).explain("queryPlanner");
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
const documents = await provider.find(database, collection, filter, { projection, limit, sort }).toArray();
|
|
43
57
|
|
|
44
58
|
const content: Array<{ text: string; type: "text" }> = [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ConnectTool } from "./
|
|
1
|
+
import { ConnectTool } from "./connect/connect.js";
|
|
2
2
|
import { ListCollectionsTool } from "./metadata/listCollections.js";
|
|
3
3
|
import { CollectionIndexesTool } from "./read/collectionIndexes.js";
|
|
4
4
|
import { ListDatabasesTool } from "./metadata/listDatabases.js";
|
|
@@ -4,14 +4,14 @@ import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
|
4
4
|
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
5
|
|
|
6
6
|
export class RenameCollectionTool extends MongoDBToolBase {
|
|
7
|
-
|
|
7
|
+
public name = "rename-collection";
|
|
8
8
|
protected description = "Renames a collection in a MongoDB database";
|
|
9
9
|
protected argsShape = {
|
|
10
10
|
...DbOperationArgs,
|
|
11
11
|
newName: z.string().describe("The new name for the collection"),
|
|
12
12
|
dropTarget: z.boolean().optional().default(false).describe("If true, drops the target collection if it exists"),
|
|
13
13
|
};
|
|
14
|
-
|
|
14
|
+
public operationType: OperationType = "update";
|
|
15
15
|
|
|
16
16
|
protected async execute({
|
|
17
17
|
database,
|
|
@@ -2,27 +2,30 @@ import { z } from "zod";
|
|
|
2
2
|
import { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
|
3
3
|
import { DbOperationArgs, MongoDBToolBase } from "../mongodbTool.js";
|
|
4
4
|
import { ToolArgs, OperationType } from "../../tool.js";
|
|
5
|
+
import { checkIndexUsage } from "../../../helpers/indexCheck.js";
|
|
5
6
|
|
|
6
7
|
export class UpdateManyTool extends MongoDBToolBase {
|
|
7
|
-
|
|
8
|
+
public name = "update-many";
|
|
8
9
|
protected description = "Updates all documents that match the specified filter for a collection";
|
|
9
10
|
protected argsShape = {
|
|
10
11
|
...DbOperationArgs,
|
|
11
12
|
filter: z
|
|
12
|
-
.
|
|
13
|
+
.object({})
|
|
14
|
+
.passthrough()
|
|
13
15
|
.optional()
|
|
14
16
|
.describe(
|
|
15
17
|
"The selection criteria for the update, matching the syntax of the filter argument of db.collection.updateOne()"
|
|
16
18
|
),
|
|
17
19
|
update: z
|
|
18
|
-
.
|
|
20
|
+
.object({})
|
|
21
|
+
.passthrough()
|
|
19
22
|
.describe("An update document describing the modifications to apply using update operator expressions"),
|
|
20
23
|
upsert: z
|
|
21
24
|
.boolean()
|
|
22
25
|
.optional()
|
|
23
26
|
.describe("Controls whether to insert a new document if no documents match the filter"),
|
|
24
27
|
};
|
|
25
|
-
|
|
28
|
+
public operationType: OperationType = "update";
|
|
26
29
|
|
|
27
30
|
protected async execute({
|
|
28
31
|
database,
|
|
@@ -32,6 +35,27 @@ export class UpdateManyTool extends MongoDBToolBase {
|
|
|
32
35
|
upsert,
|
|
33
36
|
}: ToolArgs<typeof this.argsShape>): Promise<CallToolResult> {
|
|
34
37
|
const provider = await this.ensureConnected();
|
|
38
|
+
|
|
39
|
+
// Check if update operation uses an index if enabled
|
|
40
|
+
if (this.config.indexCheck) {
|
|
41
|
+
await checkIndexUsage(provider, database, collection, "updateMany", async () => {
|
|
42
|
+
return provider.runCommandWithCheck(database, {
|
|
43
|
+
explain: {
|
|
44
|
+
update: collection,
|
|
45
|
+
updates: [
|
|
46
|
+
{
|
|
47
|
+
q: filter || {},
|
|
48
|
+
u: update,
|
|
49
|
+
upsert: upsert || false,
|
|
50
|
+
multi: true,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
},
|
|
54
|
+
verbosity: "queryPlanner",
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
35
59
|
const result = await provider.updateMany(database, collection, filter, update, {
|
|
36
60
|
upsert,
|
|
37
61
|
});
|
package/src/tools/tool.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
import { z, type ZodRawShape, type ZodNever, AnyZodObject } from "zod";
|
|
2
|
-
import type {
|
|
2
|
+
import type { RegisteredTool, ToolCallback } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
3
|
import type { CallToolResult, ToolAnnotations } from "@modelcontextprotocol/sdk/types.js";
|
|
4
|
-
import { Session } from "../session.js";
|
|
5
|
-
import logger, { LogId } from "../logger.js";
|
|
4
|
+
import { Session } from "../common/session.js";
|
|
5
|
+
import logger, { LogId } from "../common/logger.js";
|
|
6
6
|
import { Telemetry } from "../telemetry/telemetry.js";
|
|
7
7
|
import { type ToolEvent } from "../telemetry/types.js";
|
|
8
|
-
import { UserConfig } from "../config.js";
|
|
8
|
+
import { UserConfig } from "../common/config.js";
|
|
9
|
+
import { Server } from "../server.js";
|
|
9
10
|
|
|
10
11
|
export type ToolArgs<Args extends ZodRawShape> = z.objectOutputType<Args, ZodNever>;
|
|
11
12
|
|
|
12
|
-
export type OperationType = "metadata" | "read" | "create" | "delete" | "update";
|
|
13
|
+
export type OperationType = "metadata" | "read" | "create" | "delete" | "update" | "connect";
|
|
13
14
|
export type ToolCategory = "mongodb" | "atlas";
|
|
14
15
|
export type TelemetryToolMetadata = {
|
|
15
16
|
projectId?: string;
|
|
@@ -17,11 +18,11 @@ export type TelemetryToolMetadata = {
|
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
export abstract class ToolBase {
|
|
20
|
-
|
|
21
|
+
public abstract name: string;
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
public abstract category: ToolCategory;
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
public abstract operationType: OperationType;
|
|
25
26
|
|
|
26
27
|
protected abstract description: string;
|
|
27
28
|
|
|
@@ -36,6 +37,7 @@ export abstract class ToolBase {
|
|
|
36
37
|
switch (this.operationType) {
|
|
37
38
|
case "read":
|
|
38
39
|
case "metadata":
|
|
40
|
+
case "connect":
|
|
39
41
|
annotations.readOnlyHint = true;
|
|
40
42
|
annotations.destructiveHint = false;
|
|
41
43
|
break;
|
|
@@ -63,9 +65,9 @@ export abstract class ToolBase {
|
|
|
63
65
|
protected readonly telemetry: Telemetry
|
|
64
66
|
) {}
|
|
65
67
|
|
|
66
|
-
public register(server:
|
|
68
|
+
public register(server: Server): boolean {
|
|
67
69
|
if (!this.verifyAllowed()) {
|
|
68
|
-
return;
|
|
70
|
+
return false;
|
|
69
71
|
}
|
|
70
72
|
|
|
71
73
|
const callback: ToolCallback<typeof this.argsShape> = async (...args) => {
|
|
@@ -74,24 +76,25 @@ export abstract class ToolBase {
|
|
|
74
76
|
logger.debug(LogId.toolExecute, "tool", `Executing tool ${this.name}`);
|
|
75
77
|
|
|
76
78
|
const result = await this.execute(...args);
|
|
77
|
-
this.emitToolEvent(startTime, result, ...args);
|
|
79
|
+
await this.emitToolEvent(startTime, result, ...args).catch(() => {});
|
|
78
80
|
return result;
|
|
79
81
|
} catch (error: unknown) {
|
|
80
82
|
logger.error(LogId.toolExecuteFailure, "tool", `Error executing ${this.name}: ${error as string}`);
|
|
81
83
|
const toolResult = await this.handleError(error, args[0] as ToolArgs<typeof this.argsShape>);
|
|
82
|
-
this.emitToolEvent(startTime, toolResult, ...args);
|
|
84
|
+
await this.emitToolEvent(startTime, toolResult, ...args).catch(() => {});
|
|
83
85
|
return toolResult;
|
|
84
86
|
}
|
|
85
87
|
};
|
|
86
88
|
|
|
87
|
-
server.tool(this.name, this.description, this.argsShape, this.annotations, callback);
|
|
89
|
+
server.mcpServer.tool(this.name, this.description, this.argsShape, this.annotations, callback);
|
|
88
90
|
|
|
89
91
|
// This is very similar to RegisteredTool.update, but without the bugs around the name.
|
|
90
92
|
// In the upstream update method, the name is captured in the closure and not updated when
|
|
91
93
|
// the tool name changes. This means that you only get one name update before things end up
|
|
92
94
|
// in a broken state.
|
|
95
|
+
// See https://github.com/modelcontextprotocol/typescript-sdk/issues/414 for more details.
|
|
93
96
|
this.update = (updates: { name?: string; description?: string; inputSchema?: AnyZodObject }) => {
|
|
94
|
-
const tools = server["_registeredTools"] as { [toolName: string]: RegisteredTool };
|
|
97
|
+
const tools = server.mcpServer["_registeredTools"] as { [toolName: string]: RegisteredTool };
|
|
95
98
|
const existingTool = tools[this.name];
|
|
96
99
|
|
|
97
100
|
if (!existingTool) {
|
|
@@ -118,8 +121,10 @@ export abstract class ToolBase {
|
|
|
118
121
|
existingTool.inputSchema = updates.inputSchema;
|
|
119
122
|
}
|
|
120
123
|
|
|
121
|
-
server.sendToolListChanged();
|
|
124
|
+
server.mcpServer.sendToolListChanged();
|
|
122
125
|
};
|
|
126
|
+
|
|
127
|
+
return true;
|
|
123
128
|
}
|
|
124
129
|
|
|
125
130
|
protected update?: (updates: { name?: string; description?: string; inputSchema?: AnyZodObject }) => void;
|
|
@@ -179,11 +184,11 @@ export abstract class ToolBase {
|
|
|
179
184
|
* @param result - Whether the command succeeded or failed
|
|
180
185
|
* @param args - The arguments passed to the tool
|
|
181
186
|
*/
|
|
182
|
-
private emitToolEvent(
|
|
187
|
+
private async emitToolEvent(
|
|
183
188
|
startTime: number,
|
|
184
189
|
result: CallToolResult,
|
|
185
190
|
...args: Parameters<ToolCallback<typeof this.argsShape>>
|
|
186
|
-
): void {
|
|
191
|
+
): Promise<void> {
|
|
187
192
|
if (!this.telemetry.isTelemetryEnabled()) {
|
|
188
193
|
return;
|
|
189
194
|
}
|
|
@@ -209,6 +214,6 @@ export abstract class ToolBase {
|
|
|
209
214
|
event.properties.project_id = metadata.projectId;
|
|
210
215
|
}
|
|
211
216
|
|
|
212
|
-
this.telemetry.emitEvents([event]);
|
|
217
|
+
await this.telemetry.emitEvents([event]);
|
|
213
218
|
}
|
|
214
219
|
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { UserConfig } from "../common/config.js";
|
|
2
|
+
import { packageInfo } from "../common/packageInfo.js";
|
|
3
|
+
import { Server } from "../server.js";
|
|
4
|
+
import { Session } from "../common/session.js";
|
|
5
|
+
import { Telemetry } from "../telemetry/telemetry.js";
|
|
6
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
|
|
8
|
+
export abstract class TransportRunnerBase {
|
|
9
|
+
protected setupServer(userConfig: UserConfig): Server {
|
|
10
|
+
const session = new Session({
|
|
11
|
+
apiBaseUrl: userConfig.apiBaseUrl,
|
|
12
|
+
apiClientId: userConfig.apiClientId,
|
|
13
|
+
apiClientSecret: userConfig.apiClientSecret,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
const telemetry = Telemetry.create(session, userConfig);
|
|
17
|
+
|
|
18
|
+
const mcpServer = new McpServer({
|
|
19
|
+
name: packageInfo.mcpServerName,
|
|
20
|
+
version: packageInfo.version,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
return new Server({
|
|
24
|
+
mcpServer,
|
|
25
|
+
session,
|
|
26
|
+
telemetry,
|
|
27
|
+
userConfig,
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
abstract start(): Promise<void>;
|
|
32
|
+
|
|
33
|
+
abstract close(): Promise<void>;
|
|
34
|
+
}
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import logger, { LogId } from "../common/logger.js";
|
|
2
|
+
import { Server } from "../server.js";
|
|
3
|
+
import { TransportRunnerBase } from "./base.js";
|
|
1
4
|
import { JSONRPCMessage, JSONRPCMessageSchema } from "@modelcontextprotocol/sdk/types.js";
|
|
2
5
|
import { EJSON } from "bson";
|
|
3
6
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
7
|
+
import { UserConfig } from "../common/config.js";
|
|
4
8
|
|
|
5
9
|
// This is almost a copy of ReadBuffer from @modelcontextprotocol/sdk
|
|
6
10
|
// but it uses EJSON.parse instead of JSON.parse to handle BSON types
|
|
@@ -39,9 +43,34 @@ export class EJsonReadBuffer {
|
|
|
39
43
|
//
|
|
40
44
|
// This function creates a StdioServerTransport and replaces the internal readBuffer with EJsonReadBuffer
|
|
41
45
|
// that uses EJson.parse instead.
|
|
42
|
-
export function
|
|
46
|
+
export function createStdioTransport(): StdioServerTransport {
|
|
43
47
|
const server = new StdioServerTransport();
|
|
44
48
|
server["_readBuffer"] = new EJsonReadBuffer();
|
|
45
49
|
|
|
46
50
|
return server;
|
|
47
51
|
}
|
|
52
|
+
|
|
53
|
+
export class StdioRunner extends TransportRunnerBase {
|
|
54
|
+
private server: Server | undefined;
|
|
55
|
+
|
|
56
|
+
constructor(private userConfig: UserConfig) {
|
|
57
|
+
super();
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async start() {
|
|
61
|
+
try {
|
|
62
|
+
this.server = this.setupServer(this.userConfig);
|
|
63
|
+
|
|
64
|
+
const transport = createStdioTransport();
|
|
65
|
+
|
|
66
|
+
await this.server.connect(transport);
|
|
67
|
+
} catch (error: unknown) {
|
|
68
|
+
logger.emergency(LogId.serverStartFailure, "server", `Fatal error running server: ${error as string}`);
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async close(): Promise<void> {
|
|
74
|
+
await this.server?.close();
|
|
75
|
+
}
|
|
76
|
+
}
|