MCP checkbox for always allow

This commit is contained in:
Matt Rubens
2024-12-13 14:23:31 -05:00
parent 6ee118e0a2
commit 1346f1280c
26 changed files with 744 additions and 22 deletions

View File

@@ -0,0 +1,17 @@
class Client {
constructor() {
this.request = jest.fn()
}
connect() {
return Promise.resolve()
}
close() {
return Promise.resolve()
}
}
module.exports = {
Client
}

View File

@@ -0,0 +1,22 @@
class StdioClientTransport {
constructor() {
this.start = jest.fn().mockResolvedValue(undefined)
this.close = jest.fn().mockResolvedValue(undefined)
this.stderr = {
on: jest.fn()
}
}
}
class StdioServerParameters {
constructor() {
this.command = ''
this.args = []
this.env = {}
}
}
module.exports = {
StdioClientTransport,
StdioServerParameters
}

View File

@@ -0,0 +1,24 @@
const { Client } = require('./client/index.js')
const { StdioClientTransport, StdioServerParameters } = require('./client/stdio.js')
const {
CallToolResultSchema,
ListToolsResultSchema,
ListResourcesResultSchema,
ListResourceTemplatesResultSchema,
ReadResourceResultSchema,
ErrorCode,
McpError
} = require('./types.js')
module.exports = {
Client,
StdioClientTransport,
StdioServerParameters,
CallToolResultSchema,
ListToolsResultSchema,
ListResourcesResultSchema,
ListResourceTemplatesResultSchema,
ReadResourceResultSchema,
ErrorCode,
McpError
}

View File

@@ -0,0 +1,51 @@
const CallToolResultSchema = {
parse: jest.fn().mockReturnValue({})
}
const ListToolsResultSchema = {
parse: jest.fn().mockReturnValue({
tools: []
})
}
const ListResourcesResultSchema = {
parse: jest.fn().mockReturnValue({
resources: []
})
}
const ListResourceTemplatesResultSchema = {
parse: jest.fn().mockReturnValue({
resourceTemplates: []
})
}
const ReadResourceResultSchema = {
parse: jest.fn().mockReturnValue({
contents: []
})
}
const ErrorCode = {
InvalidRequest: 'InvalidRequest',
MethodNotFound: 'MethodNotFound',
InvalidParams: 'InvalidParams',
InternalError: 'InternalError'
}
class McpError extends Error {
constructor(code, message) {
super(message)
this.code = code
}
}
module.exports = {
CallToolResultSchema,
ListToolsResultSchema,
ListResourcesResultSchema,
ListResourceTemplatesResultSchema,
ReadResourceResultSchema,
ErrorCode,
McpError
}

17
src/__mocks__/McpHub.ts Normal file
View File

@@ -0,0 +1,17 @@
export class McpHub {
connections = []
isConnecting = false
constructor() {
this.toggleToolAlwaysAllow = jest.fn()
this.callTool = jest.fn()
}
async toggleToolAlwaysAllow(serverName: string, toolName: string, shouldAllow: boolean): Promise<void> {
return Promise.resolve()
}
async callTool(serverName: string, toolName: string, toolArguments?: Record<string, unknown>): Promise<any> {
return Promise.resolve({ result: 'success' })
}
}

View File

@@ -0,0 +1,12 @@
// Mock default shell based on platform
const os = require('os');
let defaultShell;
if (os.platform() === 'win32') {
defaultShell = 'cmd.exe';
} else {
defaultShell = '/bin/bash';
}
module.exports = defaultShell;
module.exports.default = defaultShell;

6
src/__mocks__/delay.js Normal file
View File

@@ -0,0 +1,6 @@
function delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
module.exports = delay;
module.exports.default = delay;

10
src/__mocks__/globby.js Normal file
View File

@@ -0,0 +1,10 @@
function globby(patterns, options) {
return Promise.resolve([]);
}
globby.sync = function(patterns, options) {
return [];
};
module.exports = globby;
module.exports.default = globby;

6
src/__mocks__/os-name.js Normal file
View File

@@ -0,0 +1,6 @@
function osName() {
return 'macOS';
}
module.exports = osName;
module.exports.default = osName;

View File

@@ -0,0 +1,20 @@
function pWaitFor(condition, options = {}) {
return new Promise((resolve, reject) => {
const interval = setInterval(() => {
if (condition()) {
clearInterval(interval);
resolve();
}
}, options.interval || 20);
if (options.timeout) {
setTimeout(() => {
clearInterval(interval);
reject(new Error('Timed out'));
}, options.timeout);
}
});
}
module.exports = pWaitFor;
module.exports.default = pWaitFor;

View File

@@ -0,0 +1,25 @@
function serializeError(error) {
if (error instanceof Error) {
return {
name: error.name,
message: error.message,
stack: error.stack
};
}
return error;
}
function deserializeError(errorData) {
if (errorData && typeof errorData === 'object') {
const error = new Error(errorData.message);
error.name = errorData.name;
error.stack = errorData.stack;
return error;
}
return errorData;
}
module.exports = {
serializeError,
deserializeError
};

View File

@@ -0,0 +1,7 @@
function stripAnsi(string) {
// Simple mock that just returns the input string
return string;
}
module.exports = stripAnsi;
module.exports.default = stripAnsi;

57
src/__mocks__/vscode.js Normal file
View File

@@ -0,0 +1,57 @@
const vscode = {
window: {
showInformationMessage: jest.fn(),
showErrorMessage: jest.fn(),
createTextEditorDecorationType: jest.fn().mockReturnValue({
dispose: jest.fn()
})
},
workspace: {
onDidSaveTextDocument: jest.fn()
},
Disposable: class {
dispose() {}
},
Uri: {
file: (path) => ({
fsPath: path,
scheme: 'file',
authority: '',
path: path,
query: '',
fragment: '',
with: jest.fn(),
toJSON: jest.fn()
})
},
EventEmitter: class {
constructor() {
this.event = jest.fn();
this.fire = jest.fn();
}
},
ConfigurationTarget: {
Global: 1,
Workspace: 2,
WorkspaceFolder: 3
},
Position: class {
constructor(line, character) {
this.line = line;
this.character = character;
}
},
Range: class {
constructor(startLine, startCharacter, endLine, endCharacter) {
this.start = new vscode.Position(startLine, startCharacter);
this.end = new vscode.Position(endLine, endCharacter);
}
},
ThemeColor: class {
constructor(id) {
this.id = id;
}
}
};
module.exports = vscode;