@codingame/monaco-vscode-mcp-service-override 16.0.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/index.d.ts +2 -0
- package/index.js +20 -0
- package/package.json +50 -0
- package/vscode/src/vs/platform/mcp/common/nativeMcpDiscoveryHelper.d.ts +9 -0
- package/vscode/src/vs/platform/mcp/common/nativeMcpDiscoveryHelper.js +5 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.d.ts +1 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcp.contribution.js +47 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.d.ts +8 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpDiscovery.js +36 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.d.ts +21 -0
- package/vscode/src/vs/workbench/contrib/mcp/browser/mcpLanguageFeatures.js +340 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.d.ts +17 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/configMcpDiscovery.js +146 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.d.ts +15 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/extensionMcpDiscovery.js +108 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/mcpDiscovery.d.ts +12 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/mcpDiscovery.js +16 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.d.ts +34 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAbstract.js +134 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.d.ts +34 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpDiscoveryAdapters.js +79 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpRemoteDiscovery.d.ts +14 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/nativeMcpRemoteDiscovery.js +44 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.d.ts +15 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/discovery/workspaceMcpDiscoveryAdapter.js +68 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigFileUtils.d.ts +6 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigFileUtils.js +30 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.d.ts +33 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpConfigPathsService.js +112 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.d.ts +59 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistry.js +322 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistryInputStorage.d.ts +27 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpRegistryInputStorage.js +134 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.d.ts +77 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServer.js +383 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.d.ts +26 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerConnection.js +114 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.d.ts +63 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpServerRequestHandler.js +318 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.d.ts +27 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/mcpService.js +220 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/modelContextProtocol.d.ts +374 -0
- package/vscode/src/vs/workbench/contrib/mcp/common/modelContextProtocol.js +14 -0
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
|
|
2
|
+
import { __decorate, __param } from '@codingame/monaco-vscode-api/external/tslib/tslib.es6';
|
|
3
|
+
import { CancellationTokenSource } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
4
|
+
import { Disposable, MutableDisposable, DisposableStore, toDisposable } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
5
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
|
6
|
+
import { localize } from '@codingame/monaco-vscode-api/vscode/vs/nls';
|
|
7
|
+
import { IInstantiationService } from '@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation';
|
|
8
|
+
import { log } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log';
|
|
9
|
+
import { McpServerRequestHandler } from './mcpServerRequestHandler.js';
|
|
10
|
+
import { McpConnectionState } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
|
|
11
|
+
import { observableValue } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/base';
|
|
12
|
+
import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/autorun';
|
|
13
|
+
|
|
14
|
+
let McpServerConnection = class McpServerConnection extends Disposable {
|
|
15
|
+
constructor(_collection, definition, _delegate, launchDefinition, _logger, _instantiationService) {
|
|
16
|
+
super();
|
|
17
|
+
this._collection = _collection;
|
|
18
|
+
this.definition = definition;
|
|
19
|
+
this._delegate = _delegate;
|
|
20
|
+
this.launchDefinition = launchDefinition;
|
|
21
|
+
this._logger = _logger;
|
|
22
|
+
this._instantiationService = _instantiationService;
|
|
23
|
+
this._launch = this._register(( new MutableDisposable()));
|
|
24
|
+
this._state = observableValue('mcpServerState', { state: McpConnectionState.Kind.Stopped });
|
|
25
|
+
this._requestHandler = observableValue('mcpServerRequestHandler', undefined);
|
|
26
|
+
this.state = this._state;
|
|
27
|
+
this.handler = this._requestHandler;
|
|
28
|
+
}
|
|
29
|
+
async start() {
|
|
30
|
+
const currentState = this._state.get();
|
|
31
|
+
if (!McpConnectionState.canBeStarted(currentState.state)) {
|
|
32
|
+
return this._waitForState(McpConnectionState.Kind.Running, McpConnectionState.Kind.Error);
|
|
33
|
+
}
|
|
34
|
+
this._launch.value = undefined;
|
|
35
|
+
this._state.set({ state: McpConnectionState.Kind.Starting }, undefined);
|
|
36
|
+
this._logger.info(( localize(7664, 'Starting server {0}', this.definition.label)));
|
|
37
|
+
try {
|
|
38
|
+
const launch = this._delegate.start(this._collection, this.definition, this.launchDefinition);
|
|
39
|
+
this._launch.value = this.adoptLaunch(launch);
|
|
40
|
+
return this._waitForState(McpConnectionState.Kind.Running, McpConnectionState.Kind.Error);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
const errorState = {
|
|
44
|
+
state: McpConnectionState.Kind.Error,
|
|
45
|
+
message: e instanceof Error ? e.message : String(e)
|
|
46
|
+
};
|
|
47
|
+
this._state.set(errorState, undefined);
|
|
48
|
+
return errorState;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
adoptLaunch(launch) {
|
|
52
|
+
const store = ( new DisposableStore());
|
|
53
|
+
const cts = ( new CancellationTokenSource());
|
|
54
|
+
store.add(toDisposable(() => cts.dispose(true)));
|
|
55
|
+
store.add(launch);
|
|
56
|
+
store.add(launch.onDidLog(({ level, message }) => {
|
|
57
|
+
log(this._logger, level, message);
|
|
58
|
+
}));
|
|
59
|
+
let didStart = false;
|
|
60
|
+
store.add(autorun(reader => {
|
|
61
|
+
const state = launch.state.read(reader);
|
|
62
|
+
this._state.set(state, undefined);
|
|
63
|
+
this._logger.info(( localize(7665, 'Connection state: {0}', (McpConnectionState.toString(state)))));
|
|
64
|
+
if (state.state === McpConnectionState.Kind.Running && !didStart) {
|
|
65
|
+
didStart = true;
|
|
66
|
+
McpServerRequestHandler.create(this._instantiationService, launch, this._logger, cts.token).then(handler => {
|
|
67
|
+
if (!store.isDisposed) {
|
|
68
|
+
this._requestHandler.set(handler, undefined);
|
|
69
|
+
}
|
|
70
|
+
else {
|
|
71
|
+
handler.dispose();
|
|
72
|
+
}
|
|
73
|
+
}, err => {
|
|
74
|
+
store.dispose();
|
|
75
|
+
if (!store.isDisposed) {
|
|
76
|
+
this._logger.error(err);
|
|
77
|
+
this._state.set({ state: McpConnectionState.Kind.Error, message: `Could not initialize MCP server: ${err.message}` }, undefined);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
}));
|
|
82
|
+
return { dispose: () => store.dispose(), object: launch };
|
|
83
|
+
}
|
|
84
|
+
async stop() {
|
|
85
|
+
this._logger.info(( localize(7666, 'Stopping server {0}', this.definition.label)));
|
|
86
|
+
this._launch.value?.object.stop();
|
|
87
|
+
await this._waitForState(McpConnectionState.Kind.Stopped, McpConnectionState.Kind.Error);
|
|
88
|
+
}
|
|
89
|
+
dispose() {
|
|
90
|
+
this._requestHandler.get()?.dispose();
|
|
91
|
+
super.dispose();
|
|
92
|
+
this._state.set({ state: McpConnectionState.Kind.Stopped }, undefined);
|
|
93
|
+
}
|
|
94
|
+
_waitForState(...kinds) {
|
|
95
|
+
const current = this._state.get();
|
|
96
|
+
if (kinds.includes(current.state)) {
|
|
97
|
+
return Promise.resolve(current);
|
|
98
|
+
}
|
|
99
|
+
return ( new Promise(resolve => {
|
|
100
|
+
const disposable = autorun(reader => {
|
|
101
|
+
const state = this._state.read(reader);
|
|
102
|
+
if (kinds.includes(state.state)) {
|
|
103
|
+
disposable.dispose();
|
|
104
|
+
resolve(state);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
McpServerConnection = ( __decorate([
|
|
111
|
+
( __param(5, IInstantiationService))
|
|
112
|
+
], McpServerConnection));
|
|
113
|
+
|
|
114
|
+
export { McpServerConnection };
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { CancellationToken } from "@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation";
|
|
2
|
+
import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
3
|
+
import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
|
|
4
|
+
import { ILogger } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log";
|
|
5
|
+
import { IMcpMessageTransport } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes";
|
|
6
|
+
import { MCP } from "./modelContextProtocol.js";
|
|
7
|
+
export interface McpRoot {
|
|
8
|
+
uri: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare class McpServerRequestHandler extends Disposable {
|
|
12
|
+
private readonly launch;
|
|
13
|
+
readonly logger: ILogger;
|
|
14
|
+
private _nextRequestId;
|
|
15
|
+
private readonly _pendingRequests;
|
|
16
|
+
private _hasAnnouncedRoots;
|
|
17
|
+
private _roots;
|
|
18
|
+
set roots(roots: MCP.Root[]);
|
|
19
|
+
private _serverInit;
|
|
20
|
+
get capabilities(): MCP.ServerCapabilities;
|
|
21
|
+
private readonly _onDidReceiveCancelledNotification;
|
|
22
|
+
readonly onDidReceiveCancelledNotification: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<MCP.CancelledNotification>;
|
|
23
|
+
private readonly _onDidReceiveProgressNotification;
|
|
24
|
+
readonly onDidReceiveProgressNotification: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<MCP.ProgressNotification>;
|
|
25
|
+
private readonly _onDidChangeResourceList;
|
|
26
|
+
readonly onDidChangeResourceList: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<void>;
|
|
27
|
+
private readonly _onDidUpdateResource;
|
|
28
|
+
readonly onDidUpdateResource: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<MCP.ResourceUpdatedNotification>;
|
|
29
|
+
private readonly _onDidChangeToolList;
|
|
30
|
+
readonly onDidChangeToolList: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<void>;
|
|
31
|
+
private readonly _onDidChangePromptList;
|
|
32
|
+
readonly onDidChangePromptList: import("@codingame/monaco-vscode-api/vscode/vs/base/common/event").Event<void>;
|
|
33
|
+
static create(instaService: IInstantiationService, launch: IMcpMessageTransport, logger: ILogger, token?: CancellationToken): Promise<McpServerRequestHandler>;
|
|
34
|
+
protected constructor(launch: IMcpMessageTransport, logger: ILogger);
|
|
35
|
+
private sendRequest;
|
|
36
|
+
private send;
|
|
37
|
+
private sendRequestPaginated;
|
|
38
|
+
private sendNotification;
|
|
39
|
+
private handleMessage;
|
|
40
|
+
private handleResult;
|
|
41
|
+
private handleError;
|
|
42
|
+
private handleServerRequest;
|
|
43
|
+
private handleServerNotification;
|
|
44
|
+
private handleCancelledNotification;
|
|
45
|
+
private handleLoggingNotification;
|
|
46
|
+
private respondToRequest;
|
|
47
|
+
private handlePing;
|
|
48
|
+
private handleRootsList;
|
|
49
|
+
private cancelAllRequests;
|
|
50
|
+
dispose(): void;
|
|
51
|
+
initialize(params: MCP.InitializeRequest["params"], token?: CancellationToken): Promise<MCP.InitializeResult>;
|
|
52
|
+
listResources(params?: MCP.ListResourcesRequest["params"], token?: CancellationToken): Promise<MCP.Resource[]>;
|
|
53
|
+
readResource(params: MCP.ReadResourceRequest["params"], token?: CancellationToken): Promise<MCP.ReadResourceResult>;
|
|
54
|
+
listResourceTemplates(params?: MCP.ListResourceTemplatesRequest["params"], token?: CancellationToken): Promise<MCP.ResourceTemplate[]>;
|
|
55
|
+
subscribe(params: MCP.SubscribeRequest["params"], token?: CancellationToken): Promise<MCP.EmptyResult>;
|
|
56
|
+
unsubscribe(params: MCP.UnsubscribeRequest["params"], token?: CancellationToken): Promise<MCP.EmptyResult>;
|
|
57
|
+
listPrompts(params?: MCP.ListPromptsRequest["params"], token?: CancellationToken): Promise<MCP.Prompt[]>;
|
|
58
|
+
getPrompt(params: MCP.GetPromptRequest["params"], token?: CancellationToken): Promise<MCP.GetPromptResult>;
|
|
59
|
+
listTools(params?: MCP.ListToolsRequest["params"], token?: CancellationToken): Promise<MCP.Tool[]>;
|
|
60
|
+
callTool(params: MCP.CallToolRequest["params"], token?: CancellationToken): Promise<MCP.CallToolResult>;
|
|
61
|
+
setLevel(params: MCP.SetLevelRequest["params"], token?: CancellationToken): Promise<MCP.EmptyResult>;
|
|
62
|
+
complete(params: MCP.CompleteRequest["params"], token?: CancellationToken): Promise<MCP.CompleteResult>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
|
|
2
|
+
import { equals } from '@codingame/monaco-vscode-api/vscode/vs/base/common/arrays';
|
|
3
|
+
import { IntervalTimer, DeferredPromise } from '@codingame/monaco-vscode-api/vscode/vs/base/common/async';
|
|
4
|
+
import { CancellationToken } from '@codingame/monaco-vscode-api/vscode/vs/base/common/cancellation';
|
|
5
|
+
import { CancellationError } from '@codingame/monaco-vscode-api/vscode/vs/base/common/errors';
|
|
6
|
+
import { Emitter } from '@codingame/monaco-vscode-api/vscode/vs/base/common/event';
|
|
7
|
+
import { Disposable, DisposableStore } from '@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle';
|
|
8
|
+
import '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/index';
|
|
9
|
+
import { canLog, LogLevel } from '@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log';
|
|
10
|
+
import { IProductService } from '@codingame/monaco-vscode-api/vscode/vs/platform/product/common/productService.service';
|
|
11
|
+
import { McpConnectionState, MpcResponseError } from '@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes';
|
|
12
|
+
import { MCP } from './modelContextProtocol.js';
|
|
13
|
+
import { autorun } from '@codingame/monaco-vscode-api/vscode/vs/base/common/observableInternal/autorun';
|
|
14
|
+
|
|
15
|
+
class McpServerRequestHandler extends Disposable {
|
|
16
|
+
set roots(roots) {
|
|
17
|
+
if (!equals(this._roots, roots)) {
|
|
18
|
+
this._roots = roots;
|
|
19
|
+
if (this._hasAnnouncedRoots) {
|
|
20
|
+
this.sendNotification({ method: 'notifications/roots/list_changed' });
|
|
21
|
+
this._hasAnnouncedRoots = false;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
get capabilities() {
|
|
26
|
+
return this._serverInit.capabilities;
|
|
27
|
+
}
|
|
28
|
+
static async create(instaService, launch, logger, token) {
|
|
29
|
+
const mcp = ( new McpServerRequestHandler(launch, logger));
|
|
30
|
+
const store = ( new DisposableStore());
|
|
31
|
+
try {
|
|
32
|
+
const timer = store.add(( new IntervalTimer()));
|
|
33
|
+
timer.cancelAndSet(() => {
|
|
34
|
+
logger.info('Waiting for server to respond to `initialize` request...');
|
|
35
|
+
}, 5000);
|
|
36
|
+
await instaService.invokeFunction(async (accessor) => {
|
|
37
|
+
const productService = accessor.get(IProductService);
|
|
38
|
+
const initialized = await mcp.sendRequest({
|
|
39
|
+
method: 'initialize',
|
|
40
|
+
params: {
|
|
41
|
+
protocolVersion: MCP.LATEST_PROTOCOL_VERSION,
|
|
42
|
+
capabilities: {
|
|
43
|
+
roots: { listChanged: true },
|
|
44
|
+
},
|
|
45
|
+
clientInfo: {
|
|
46
|
+
name: productService.nameLong,
|
|
47
|
+
version: productService.version,
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}, token);
|
|
51
|
+
mcp._serverInit = initialized;
|
|
52
|
+
mcp.sendNotification({
|
|
53
|
+
method: 'notifications/initialized'
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
return mcp;
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
mcp.dispose();
|
|
60
|
+
throw e;
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
store.dispose();
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
constructor(launch, logger) {
|
|
67
|
+
super();
|
|
68
|
+
this.launch = launch;
|
|
69
|
+
this.logger = logger;
|
|
70
|
+
this._nextRequestId = 1;
|
|
71
|
+
this._pendingRequests = ( new Map());
|
|
72
|
+
this._hasAnnouncedRoots = false;
|
|
73
|
+
this._roots = [];
|
|
74
|
+
this._onDidReceiveCancelledNotification = this._register(( new Emitter()));
|
|
75
|
+
this.onDidReceiveCancelledNotification = this._onDidReceiveCancelledNotification.event;
|
|
76
|
+
this._onDidReceiveProgressNotification = this._register(( new Emitter()));
|
|
77
|
+
this.onDidReceiveProgressNotification = this._onDidReceiveProgressNotification.event;
|
|
78
|
+
this._onDidChangeResourceList = this._register(( new Emitter()));
|
|
79
|
+
this.onDidChangeResourceList = this._onDidChangeResourceList.event;
|
|
80
|
+
this._onDidUpdateResource = this._register(( new Emitter()));
|
|
81
|
+
this.onDidUpdateResource = this._onDidUpdateResource.event;
|
|
82
|
+
this._onDidChangeToolList = this._register(( new Emitter()));
|
|
83
|
+
this.onDidChangeToolList = this._onDidChangeToolList.event;
|
|
84
|
+
this._onDidChangePromptList = this._register(( new Emitter()));
|
|
85
|
+
this.onDidChangePromptList = this._onDidChangePromptList.event;
|
|
86
|
+
this._register(launch.onDidReceiveMessage(message => this.handleMessage(message)));
|
|
87
|
+
this._register(autorun(reader => {
|
|
88
|
+
const state = launch.state.read(reader).state;
|
|
89
|
+
if (state === McpConnectionState.Kind.Error || state === McpConnectionState.Kind.Stopped) {
|
|
90
|
+
this.cancelAllRequests();
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
async sendRequest(request, token = CancellationToken.None) {
|
|
95
|
+
if (this._store.isDisposed) {
|
|
96
|
+
return Promise.reject(( new CancellationError()));
|
|
97
|
+
}
|
|
98
|
+
const id = this._nextRequestId++;
|
|
99
|
+
const jsonRpcRequest = {
|
|
100
|
+
jsonrpc: MCP.JSONRPC_VERSION,
|
|
101
|
+
id,
|
|
102
|
+
...request
|
|
103
|
+
};
|
|
104
|
+
const promise = ( new DeferredPromise());
|
|
105
|
+
this._pendingRequests.set(id, { promise });
|
|
106
|
+
const cancelListener = token.onCancellationRequested(() => {
|
|
107
|
+
if (!promise.isSettled) {
|
|
108
|
+
this._pendingRequests.delete(id);
|
|
109
|
+
this.sendNotification({ method: 'notifications/cancelled', params: { requestId: id } });
|
|
110
|
+
promise.cancel();
|
|
111
|
+
}
|
|
112
|
+
cancelListener.dispose();
|
|
113
|
+
});
|
|
114
|
+
this.send(jsonRpcRequest);
|
|
115
|
+
const ret = promise.p.finally(() => {
|
|
116
|
+
cancelListener.dispose();
|
|
117
|
+
this._pendingRequests.delete(id);
|
|
118
|
+
});
|
|
119
|
+
return ret;
|
|
120
|
+
}
|
|
121
|
+
send(mcp) {
|
|
122
|
+
if (canLog(this.logger.getLevel(), LogLevel.Debug)) {
|
|
123
|
+
this.logger.debug(`[editor -> server] ${JSON.stringify(mcp)}`);
|
|
124
|
+
}
|
|
125
|
+
this.launch.send(mcp);
|
|
126
|
+
}
|
|
127
|
+
async sendRequestPaginated(method, getItems, initialParams, token = CancellationToken.None) {
|
|
128
|
+
let allItems = [];
|
|
129
|
+
let nextCursor = undefined;
|
|
130
|
+
do {
|
|
131
|
+
const params = {
|
|
132
|
+
...initialParams,
|
|
133
|
+
cursor: nextCursor
|
|
134
|
+
};
|
|
135
|
+
const result = await this.sendRequest({ method, params }, token);
|
|
136
|
+
allItems = allItems.concat(getItems(result));
|
|
137
|
+
nextCursor = result.nextCursor;
|
|
138
|
+
} while (nextCursor !== undefined && !token.isCancellationRequested);
|
|
139
|
+
return allItems;
|
|
140
|
+
}
|
|
141
|
+
sendNotification(notification) {
|
|
142
|
+
this.send({ ...notification, jsonrpc: MCP.JSONRPC_VERSION });
|
|
143
|
+
}
|
|
144
|
+
handleMessage(message) {
|
|
145
|
+
if (canLog(this.logger.getLevel(), LogLevel.Debug)) {
|
|
146
|
+
this.logger.debug(`[server <- editor] ${JSON.stringify(message)}`);
|
|
147
|
+
}
|
|
148
|
+
if ('id' in message) {
|
|
149
|
+
if ('result' in message) {
|
|
150
|
+
this.handleResult(message);
|
|
151
|
+
}
|
|
152
|
+
else if ('error' in message) {
|
|
153
|
+
this.handleError(message);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
if ('method' in message) {
|
|
157
|
+
if ('id' in message) {
|
|
158
|
+
this.handleServerRequest(message);
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
this.handleServerNotification(message);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
handleResult(response) {
|
|
166
|
+
const request = this._pendingRequests.get(response.id);
|
|
167
|
+
if (request) {
|
|
168
|
+
this._pendingRequests.delete(response.id);
|
|
169
|
+
request.promise.complete(response.result);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
handleError(response) {
|
|
173
|
+
const request = this._pendingRequests.get(response.id);
|
|
174
|
+
if (request) {
|
|
175
|
+
this._pendingRequests.delete(response.id);
|
|
176
|
+
request.promise.error(( new MpcResponseError(response.error.message, response.error.code, response.error.data)));
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
handleServerRequest(request) {
|
|
180
|
+
switch (request.method) {
|
|
181
|
+
case 'ping':
|
|
182
|
+
return this.respondToRequest(request, this.handlePing(request));
|
|
183
|
+
case 'roots/list':
|
|
184
|
+
return this.respondToRequest(request, this.handleRootsList(request));
|
|
185
|
+
default: {
|
|
186
|
+
const errorResponse = {
|
|
187
|
+
jsonrpc: MCP.JSONRPC_VERSION,
|
|
188
|
+
id: request.id,
|
|
189
|
+
error: {
|
|
190
|
+
code: MCP.METHOD_NOT_FOUND,
|
|
191
|
+
message: `Method not found: ${request.method}`
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
this.send(errorResponse);
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
handleServerNotification(request) {
|
|
200
|
+
switch (request.method) {
|
|
201
|
+
case 'notifications/message':
|
|
202
|
+
return this.handleLoggingNotification(request);
|
|
203
|
+
case 'notifications/cancelled':
|
|
204
|
+
this._onDidReceiveCancelledNotification.fire(request);
|
|
205
|
+
return this.handleCancelledNotification(request);
|
|
206
|
+
case 'notifications/progress':
|
|
207
|
+
this._onDidReceiveProgressNotification.fire(request);
|
|
208
|
+
return;
|
|
209
|
+
case 'notifications/resources/list_changed':
|
|
210
|
+
this._onDidChangeResourceList.fire();
|
|
211
|
+
return;
|
|
212
|
+
case 'notifications/resources/updated':
|
|
213
|
+
this._onDidUpdateResource.fire(request);
|
|
214
|
+
return;
|
|
215
|
+
case 'notifications/tools/list_changed':
|
|
216
|
+
this._onDidChangeToolList.fire();
|
|
217
|
+
return;
|
|
218
|
+
case 'notifications/prompts/list_changed':
|
|
219
|
+
this._onDidChangePromptList.fire();
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
handleCancelledNotification(request) {
|
|
224
|
+
const pendingRequest = this._pendingRequests.get(request.params.requestId);
|
|
225
|
+
if (pendingRequest) {
|
|
226
|
+
this._pendingRequests.delete(request.params.requestId);
|
|
227
|
+
pendingRequest.promise.cancel();
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
handleLoggingNotification(request) {
|
|
231
|
+
let contents = typeof request.params.data === 'string' ? request.params.data : JSON.stringify(request.params.data);
|
|
232
|
+
if (request.params.logger) {
|
|
233
|
+
contents = `${request.params.logger}: ${contents}`;
|
|
234
|
+
}
|
|
235
|
+
switch (request.params?.level) {
|
|
236
|
+
case 'debug':
|
|
237
|
+
this.logger.debug(contents);
|
|
238
|
+
break;
|
|
239
|
+
case 'info':
|
|
240
|
+
case 'notice':
|
|
241
|
+
this.logger.info(contents);
|
|
242
|
+
break;
|
|
243
|
+
case 'warning':
|
|
244
|
+
this.logger.warn(contents);
|
|
245
|
+
break;
|
|
246
|
+
case 'error':
|
|
247
|
+
case 'critical':
|
|
248
|
+
case 'alert':
|
|
249
|
+
case 'emergency':
|
|
250
|
+
this.logger.error(contents);
|
|
251
|
+
break;
|
|
252
|
+
default:
|
|
253
|
+
this.logger.info(contents);
|
|
254
|
+
break;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
respondToRequest(request, result) {
|
|
258
|
+
const response = {
|
|
259
|
+
jsonrpc: MCP.JSONRPC_VERSION,
|
|
260
|
+
id: request.id,
|
|
261
|
+
result
|
|
262
|
+
};
|
|
263
|
+
this.send(response);
|
|
264
|
+
}
|
|
265
|
+
handlePing(_request) {
|
|
266
|
+
return {};
|
|
267
|
+
}
|
|
268
|
+
handleRootsList(_request) {
|
|
269
|
+
this._hasAnnouncedRoots = true;
|
|
270
|
+
return { roots: this._roots };
|
|
271
|
+
}
|
|
272
|
+
cancelAllRequests() {
|
|
273
|
+
this._pendingRequests.forEach(pending => pending.promise.cancel());
|
|
274
|
+
this._pendingRequests.clear();
|
|
275
|
+
}
|
|
276
|
+
dispose() {
|
|
277
|
+
this.cancelAllRequests();
|
|
278
|
+
super.dispose();
|
|
279
|
+
}
|
|
280
|
+
initialize(params, token) {
|
|
281
|
+
return this.sendRequest({ method: 'initialize', params }, token);
|
|
282
|
+
}
|
|
283
|
+
listResources(params, token) {
|
|
284
|
+
return this.sendRequestPaginated('resources/list', result => result.resources, params, token);
|
|
285
|
+
}
|
|
286
|
+
readResource(params, token) {
|
|
287
|
+
return this.sendRequest({ method: 'resources/read', params }, token);
|
|
288
|
+
}
|
|
289
|
+
listResourceTemplates(params, token) {
|
|
290
|
+
return this.sendRequestPaginated('resources/templates/list', result => result.resourceTemplates, params, token);
|
|
291
|
+
}
|
|
292
|
+
subscribe(params, token) {
|
|
293
|
+
return this.sendRequest({ method: 'resources/subscribe', params }, token);
|
|
294
|
+
}
|
|
295
|
+
unsubscribe(params, token) {
|
|
296
|
+
return this.sendRequest({ method: 'resources/unsubscribe', params }, token);
|
|
297
|
+
}
|
|
298
|
+
listPrompts(params, token) {
|
|
299
|
+
return this.sendRequestPaginated('prompts/list', result => result.prompts, params, token);
|
|
300
|
+
}
|
|
301
|
+
getPrompt(params, token) {
|
|
302
|
+
return this.sendRequest({ method: 'prompts/get', params }, token);
|
|
303
|
+
}
|
|
304
|
+
listTools(params, token) {
|
|
305
|
+
return this.sendRequestPaginated('tools/list', result => result.tools, params, token);
|
|
306
|
+
}
|
|
307
|
+
callTool(params, token) {
|
|
308
|
+
return this.sendRequest({ method: 'tools/call', params }, token);
|
|
309
|
+
}
|
|
310
|
+
setLevel(params, token) {
|
|
311
|
+
return this.sendRequest({ method: 'logging/setLevel', params }, token);
|
|
312
|
+
}
|
|
313
|
+
complete(params, token) {
|
|
314
|
+
return this.sendRequest({ method: 'completion/complete', params }, token);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
export { McpServerRequestHandler };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Disposable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/lifecycle";
|
|
2
|
+
import { IObservable } from "@codingame/monaco-vscode-api/vscode/vs/base/common/observable";
|
|
3
|
+
import { IInstantiationService } from "@codingame/monaco-vscode-api/vscode/vs/platform/instantiation/common/instantiation";
|
|
4
|
+
import { ILogService } from "@codingame/monaco-vscode-api/vscode/vs/platform/log/common/log.service";
|
|
5
|
+
import { ILanguageModelToolsService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/chat/common/languageModelToolsService.service";
|
|
6
|
+
import { IMcpRegistry } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpRegistryTypes.service";
|
|
7
|
+
import { McpServerMetadataCache } from "./mcpServer.js";
|
|
8
|
+
import { IMcpServer } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes";
|
|
9
|
+
import { IMcpService } from "@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes.service";
|
|
10
|
+
export declare class McpService extends Disposable implements IMcpService {
|
|
11
|
+
private readonly _instantiationService;
|
|
12
|
+
private readonly _mcpRegistry;
|
|
13
|
+
private readonly _toolsService;
|
|
14
|
+
private readonly _logService;
|
|
15
|
+
_serviceBrand: undefined;
|
|
16
|
+
private readonly _servers;
|
|
17
|
+
readonly servers: IObservable<readonly IMcpServer[]>;
|
|
18
|
+
get lazyCollectionState(): IObservable<import("@codingame/monaco-vscode-api/vscode/vs/workbench/contrib/mcp/common/mcpTypes").LazyCollectionState>;
|
|
19
|
+
protected readonly userCache: McpServerMetadataCache;
|
|
20
|
+
protected readonly workspaceCache: McpServerMetadataCache;
|
|
21
|
+
constructor(_instantiationService: IInstantiationService, _mcpRegistry: IMcpRegistry, _toolsService: ILanguageModelToolsService, _logService: ILogService);
|
|
22
|
+
resetCaches(): void;
|
|
23
|
+
activateCollections(): Promise<void>;
|
|
24
|
+
private _syncTools;
|
|
25
|
+
private _updateCollectedServers;
|
|
26
|
+
dispose(): void;
|
|
27
|
+
}
|