-
Notifications
You must be signed in to change notification settings - Fork 90
chore: adds vscode specific connection error handler MCP-132 #1113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
himanshusinghs
merged 4 commits into
feat/mcp-integration
from
chore/MCP-132-vscode-connection-error-handler
Sep 3, 2025
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { | ||
ErrorCodes, | ||
type ConnectionErrorHandler, | ||
} from '@himanshusinghs/mongodb-mcp-server'; | ||
import type ConnectionController from '../connectionController'; | ||
|
||
export const createMCPConnectionErrorHandler = ( | ||
connectionController: Pick< | ||
ConnectionController, | ||
'getSavedConnections' | 'getActiveConnectionName' | ||
>, | ||
): ConnectionErrorHandler => { | ||
return (error) => { | ||
const activeConnectionName = connectionController.getActiveConnectionName(); | ||
const availableConnections = connectionController | ||
.getSavedConnections() | ||
.map(({ name }) => ({ name })); | ||
|
||
const connectionGuidance: string[] = availableConnections.length | ||
? [ | ||
`Following connections are available in the Sidebar for the user to connect to: ${JSON.stringify(availableConnections)}. Note to LLM: Provide user with the list of connections available and ask them to select a connection in the Sidebar.`, | ||
'Note to LLM: Alternatively, if the user wish to establish a new MongoDB connection, then ask them to follow our official guide on the following link: https://www.mongodb.com/docs/mongodb-vscode/connect/#create-a-connection', | ||
] | ||
: [ | ||
'The user has no connections saved in their MongoDB Extension sidebar.', | ||
'Note to LLM: Ask the user to follow our official guide on the following link: https://www.mongodb.com/docs/mongodb-vscode/connect/#create-a-connection to connect to a MongoDB cluster.', | ||
]; | ||
|
||
switch (error.code) { | ||
case ErrorCodes.NotConnectedToMongoDB: | ||
return { | ||
errorHandled: true, | ||
result: { | ||
content: [ | ||
{ | ||
type: 'text', | ||
text: 'You need to connect to a MongoDB instance before you can access its data.', | ||
}, | ||
...connectionGuidance.map<{ type: 'text'; text: string }>( | ||
(text) => ({ type: 'text', text }), | ||
), | ||
], | ||
}, | ||
}; | ||
case ErrorCodes.MisconfiguredConnectionString: { | ||
const resolutionGuidance: string[] = [ | ||
'Note to LLM: Ask the user to reconnect to the desired connection. If the problem persist even after that then advice them to raise an issue on the VSCode project board - https://github.com/mongodb-js/vscode/issues', | ||
...connectionGuidance, | ||
]; | ||
return { | ||
errorHandled: true, | ||
result: { | ||
content: [ | ||
{ | ||
type: 'text', | ||
text: `MCP server is having trouble connecting to ${activeConnectionName ? activeConnectionName : 'the selected connection in the MongoDB VSCode extension'}.`, | ||
}, | ||
...resolutionGuidance.map<{ type: 'text'; text: string }>( | ||
(text) => ({ type: 'text', text }), | ||
), | ||
], | ||
}, | ||
}; | ||
} | ||
default: | ||
return { | ||
errorHandled: false, | ||
}; | ||
} | ||
}; | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import { expect } from 'chai'; | ||
import { beforeEach } from 'mocha'; | ||
import { createMCPConnectionErrorHandler } from '../../../mcp/mcpConnectionErrorHandler'; | ||
import ConnectionController from '../../../connectionController'; | ||
import { ExtensionContextStub } from '../stubs'; | ||
import { StorageController } from '../../../storage'; | ||
import { TelemetryService } from '../../../telemetry'; | ||
import { StatusView } from '../../../views'; | ||
import type { | ||
ConnectionErrorHandled, | ||
ConnectionErrorHandlerContext, | ||
} from '@himanshusinghs/mongodb-mcp-server'; | ||
import { ErrorCodes } from '@himanshusinghs/mongodb-mcp-server'; | ||
|
||
class MongoDBError extends Error { | ||
constructor( | ||
public code: | ||
| ErrorCodes.NotConnectedToMongoDB | ||
| ErrorCodes.MisconfiguredConnectionString, | ||
message: string, | ||
) { | ||
super(message); | ||
} | ||
} | ||
|
||
suite('mcpConnectionErrorHandler suite', () => { | ||
let connectionController: ConnectionController; | ||
beforeEach(() => { | ||
const extensionContext = new ExtensionContextStub(); | ||
const testStorageController = new StorageController(extensionContext); | ||
const testTelemetryService = new TelemetryService( | ||
testStorageController, | ||
extensionContext, | ||
); | ||
connectionController = new ConnectionController({ | ||
statusView: new StatusView(extensionContext), | ||
storageController: testStorageController, | ||
telemetryService: testTelemetryService, | ||
}); | ||
}); | ||
|
||
test('should handle NotConnectedToMongoDB error', () => { | ||
const handler = createMCPConnectionErrorHandler(connectionController); | ||
const result = handler( | ||
new MongoDBError( | ||
ErrorCodes.NotConnectedToMongoDB, | ||
'Not connected to MongoDB', | ||
), | ||
{} as ConnectionErrorHandlerContext, | ||
) as ConnectionErrorHandled; | ||
|
||
expect(result.errorHandled).to.be.true; | ||
expect(result.result.content).to.deep.contain({ | ||
type: 'text', | ||
text: 'You need to connect to a MongoDB instance before you can access its data.', | ||
}); | ||
}); | ||
|
||
test('should handle MisconfiguredConnectionString error', () => { | ||
const handler = createMCPConnectionErrorHandler(connectionController); | ||
const result = handler( | ||
new MongoDBError( | ||
ErrorCodes.MisconfiguredConnectionString, | ||
'Misconfigured MongoDB string', | ||
), | ||
{} as ConnectionErrorHandlerContext, | ||
) as ConnectionErrorHandled; | ||
|
||
expect(result.errorHandled).to.be.true; | ||
expect(result.result.content).to.deep.contain({ | ||
type: 'text', | ||
text: 'MCP server is having trouble connecting to the selected connection in the MongoDB VSCode extension.', | ||
}); | ||
}); | ||
|
||
test('should not handle any other errors', () => { | ||
const handler = createMCPConnectionErrorHandler(connectionController); | ||
expect( | ||
handler( | ||
new MongoDBError(ErrorCodes.ForbiddenCollscan as any, 'Some error'), | ||
{} as any, | ||
), | ||
).to.deep.equal({ | ||
errorHandled: false, | ||
}); | ||
expect(handler(new Error('Some error') as any, {} as any)).to.deep.equal({ | ||
errorHandled: false, | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the pick here - why not just get the complete controller?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because the code does not really depend on anything more than the required methods and the consuming side shouldn't have to be bound to pass anything more than the required methods?