@theia/ai-mcp 1.57.0-next.112

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.
Files changed (57) hide show
  1. package/README.md +91 -0
  2. package/lib/browser/mcp-command-contribution.d.ts +21 -0
  3. package/lib/browser/mcp-command-contribution.d.ts.map +1 -0
  4. package/lib/browser/mcp-command-contribution.js +114 -0
  5. package/lib/browser/mcp-command-contribution.js.map +1 -0
  6. package/lib/browser/mcp-frontend-application-contribution.d.ts +30 -0
  7. package/lib/browser/mcp-frontend-application-contribution.d.ts.map +1 -0
  8. package/lib/browser/mcp-frontend-application-contribution.js +145 -0
  9. package/lib/browser/mcp-frontend-application-contribution.js.map +1 -0
  10. package/lib/browser/mcp-frontend-module.d.ts +4 -0
  11. package/lib/browser/mcp-frontend-module.d.ts.map +1 -0
  12. package/lib/browser/mcp-frontend-module.js +36 -0
  13. package/lib/browser/mcp-frontend-module.js.map +1 -0
  14. package/lib/browser/mcp-frontend-service.d.ts +15 -0
  15. package/lib/browser/mcp-frontend-service.d.ts.map +1 -0
  16. package/lib/browser/mcp-frontend-service.js +88 -0
  17. package/lib/browser/mcp-frontend-service.js.map +1 -0
  18. package/lib/browser/mcp-preferences.d.ts +4 -0
  19. package/lib/browser/mcp-preferences.d.ts.map +1 -0
  20. package/lib/browser/mcp-preferences.js +90 -0
  21. package/lib/browser/mcp-preferences.js.map +1 -0
  22. package/lib/common/index.d.ts +2 -0
  23. package/lib/common/index.d.ts.map +1 -0
  24. package/lib/common/index.js +20 -0
  25. package/lib/common/index.js.map +1 -0
  26. package/lib/common/mcp-server-manager.d.ts +42 -0
  27. package/lib/common/mcp-server-manager.d.ts.map +1 -0
  28. package/lib/common/mcp-server-manager.js +21 -0
  29. package/lib/common/mcp-server-manager.js.map +1 -0
  30. package/lib/node/mcp-backend-module.d.ts +4 -0
  31. package/lib/node/mcp-backend-module.d.ts.map +1 -0
  32. package/lib/node/mcp-backend-module.js +34 -0
  33. package/lib/node/mcp-backend-module.js.map +1 -0
  34. package/lib/node/mcp-server-manager-impl.d.ts +14 -0
  35. package/lib/node/mcp-server-manager-impl.d.ts.map +1 -0
  36. package/lib/node/mcp-server-manager-impl.js +93 -0
  37. package/lib/node/mcp-server-manager-impl.js.map +1 -0
  38. package/lib/node/mcp-server.d.ts +19 -0
  39. package/lib/node/mcp-server.d.ts.map +1 -0
  40. package/lib/node/mcp-server.js +97 -0
  41. package/lib/node/mcp-server.js.map +1 -0
  42. package/lib/package.spec.d.ts +1 -0
  43. package/lib/package.spec.d.ts.map +1 -0
  44. package/lib/package.spec.js +26 -0
  45. package/lib/package.spec.js.map +1 -0
  46. package/package.json +50 -0
  47. package/src/browser/mcp-command-contribution.ts +106 -0
  48. package/src/browser/mcp-frontend-application-contribution.ts +158 -0
  49. package/src/browser/mcp-frontend-module.ts +35 -0
  50. package/src/browser/mcp-frontend-service.ts +87 -0
  51. package/src/browser/mcp-preferences.ts +90 -0
  52. package/src/common/index.ts +16 -0
  53. package/src/common/mcp-server-manager.ts +63 -0
  54. package/src/node/mcp-backend-module.ts +37 -0
  55. package/src/node/mcp-server-manager-impl.ts +93 -0
  56. package/src/node/mcp-server.ts +111 -0
  57. package/src/package.spec.ts +28 -0
@@ -0,0 +1,106 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ import { AICommandHandlerFactory } from '@theia/ai-core/lib/browser/ai-command-handler-factory';
17
+ import { CommandContribution, CommandRegistry, MessageService } from '@theia/core';
18
+ import { QuickInputService } from '@theia/core/lib/browser';
19
+ import { inject, injectable } from '@theia/core/shared/inversify';
20
+ import { MCPFrontendService } from './mcp-frontend-service';
21
+
22
+ export const StartMCPServer = {
23
+ id: 'mcp.startserver',
24
+ label: 'MCP: Start MCP Server',
25
+ };
26
+ export const StopMCPServer = {
27
+ id: 'mcp.stopserver',
28
+ label: 'MCP: Stop MCP Server',
29
+ };
30
+
31
+ @injectable()
32
+ export class MCPCommandContribution implements CommandContribution {
33
+ @inject(AICommandHandlerFactory)
34
+ protected readonly commandHandlerFactory: AICommandHandlerFactory;
35
+
36
+ @inject(QuickInputService)
37
+ protected readonly quickInputService: QuickInputService;
38
+
39
+ @inject(MessageService)
40
+ protected messageService: MessageService;
41
+
42
+ @inject(MCPFrontendService)
43
+ protected readonly mcpFrontendService: MCPFrontendService;
44
+
45
+ private async getMCPServerSelection(serverNames: string[]): Promise<string | undefined> {
46
+ if (!serverNames || serverNames.length === 0) {
47
+ return undefined;
48
+ }
49
+ const options = serverNames.map(mcpServerName => ({ label: mcpServerName }));
50
+ const result = await this.quickInputService.showQuickPick(options);
51
+ return result?.label;
52
+ }
53
+
54
+ registerCommands(commandRegistry: CommandRegistry): void {
55
+ commandRegistry.registerCommand(StopMCPServer, this.commandHandlerFactory({
56
+ execute: async () => {
57
+ try {
58
+ const startedServers = await this.mcpFrontendService.getStartedServers();
59
+ if (!startedServers || startedServers.length === 0) {
60
+ this.messageService.error('No MCP servers running.');
61
+ return;
62
+ }
63
+ const selection = await this.getMCPServerSelection(startedServers);
64
+ if (!selection) {
65
+ return;
66
+ }
67
+ await this.mcpFrontendService.stopServer(selection);
68
+ } catch (error) {
69
+ console.error('Error while stopping MCP server:', error);
70
+ }
71
+ }
72
+ }));
73
+
74
+ commandRegistry.registerCommand(StartMCPServer, this.commandHandlerFactory({
75
+ execute: async () => {
76
+ try {
77
+ const servers = await this.mcpFrontendService.getServerNames();
78
+ const startedServers = await this.mcpFrontendService.getStartedServers();
79
+ const startableServers = servers.filter(server => !startedServers.includes(server));
80
+ if (!startableServers || startableServers.length === 0) {
81
+ if (startedServers && startedServers.length > 0) {
82
+ this.messageService.error('All MCP servers are already running.');
83
+ } else {
84
+ this.messageService.error('No MCP servers configured.');
85
+ }
86
+ return;
87
+ }
88
+
89
+ const selection = await this.getMCPServerSelection(startableServers);
90
+ if (!selection) {
91
+ return;
92
+ }
93
+ await this.mcpFrontendService.startServer(selection);
94
+ const { tools } = await this.mcpFrontendService.getTools(selection);
95
+ const toolNames = tools.map(tool => tool.name || 'Unnamed Tool').join(', ');
96
+ this.messageService.info(
97
+ `MCP server "${selection}" successfully started. Registered tools: ${toolNames || 'No tools available.'}`
98
+ );
99
+ } catch (error) {
100
+ this.messageService.error('An error occurred while starting the MCP server.');
101
+ console.error('Error while starting MCP server:', error);
102
+ }
103
+ }
104
+ }));
105
+ }
106
+ }
@@ -0,0 +1,158 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { FrontendApplicationContribution, PreferenceProvider, PreferenceService } from '@theia/core/lib/browser';
18
+ import { inject, injectable } from '@theia/core/shared/inversify';
19
+ import { MCPServerDescription, MCPServerManager } from '../common';
20
+ import { MCP_SERVERS_PREF } from './mcp-preferences';
21
+ import { JSONObject } from '@theia/core/shared/@phosphor/coreutils';
22
+ import { MCPFrontendService } from './mcp-frontend-service';
23
+
24
+ interface MCPServersPreferenceValue {
25
+ command: string;
26
+ args?: string[];
27
+ env?: { [key: string]: string };
28
+ autostart?: boolean;
29
+ };
30
+
31
+ interface MCPServersPreference {
32
+ [name: string]: MCPServersPreferenceValue
33
+ };
34
+
35
+ namespace MCPServersPreference {
36
+ export function isValue(obj: unknown): obj is MCPServersPreferenceValue {
37
+ return !!obj && typeof obj === 'object' &&
38
+ 'command' in obj && typeof obj.command === 'string' &&
39
+ (!('args' in obj) || Array.isArray(obj.args) && obj.args.every(arg => typeof arg === 'string')) &&
40
+ (!('env' in obj) || !!obj.env && typeof obj.env === 'object' && Object.values(obj.env).every(value => typeof value === 'string')) &&
41
+ (!('autostart' in obj) || typeof obj.autostart === 'boolean');
42
+ }
43
+ }
44
+
45
+ function filterValidValues(servers: unknown): MCPServersPreference {
46
+ const result: MCPServersPreference = {};
47
+ if (!servers || typeof servers !== 'object') {
48
+ return result;
49
+ }
50
+ for (const [name, value] of Object.entries(servers)) {
51
+ if (typeof name === 'string' && MCPServersPreference.isValue(value)) {
52
+ result[name] = value;
53
+ }
54
+ }
55
+ return result;
56
+ }
57
+
58
+ @injectable()
59
+ export class McpFrontendApplicationContribution implements FrontendApplicationContribution {
60
+
61
+ @inject(PreferenceService)
62
+ protected preferenceService: PreferenceService;
63
+
64
+ @inject(MCPServerManager)
65
+ protected manager: MCPServerManager;
66
+
67
+ @inject(MCPFrontendService)
68
+ protected frontendMCPService: MCPFrontendService;
69
+
70
+ protected prevServers: Map<string, MCPServerDescription> = new Map();
71
+
72
+ onStart(): void {
73
+ this.preferenceService.ready.then(() => {
74
+ const servers = filterValidValues(this.preferenceService.get(
75
+ MCP_SERVERS_PREF,
76
+ {}
77
+ ));
78
+ this.prevServers = this.convertToMap(servers);
79
+ this.syncServers(this.prevServers);
80
+ this.autoStartServers(this.prevServers);
81
+
82
+ this.preferenceService.onPreferenceChanged(event => {
83
+ if (event.preferenceName === MCP_SERVERS_PREF) {
84
+ this.handleServerChanges(filterValidValues(event.newValue));
85
+ }
86
+ });
87
+ });
88
+ this.frontendMCPService.registerToolsForAllStartedServers();
89
+ }
90
+
91
+ protected async autoStartServers(servers: Map<string, MCPServerDescription>): Promise<void> {
92
+ const startedServers = await this.frontendMCPService.getStartedServers();
93
+ for (const [name, serverDesc] of servers) {
94
+ if (serverDesc && serverDesc.autostart) {
95
+ if (!startedServers.includes(name)) {
96
+ await this.frontendMCPService.startServer(name);
97
+ }
98
+ }
99
+ }
100
+ }
101
+
102
+ protected handleServerChanges(newServers: MCPServersPreference): void {
103
+ const oldServers = this.prevServers;
104
+ const updatedServers = this.convertToMap(newServers);
105
+
106
+ for (const [name] of oldServers) {
107
+ if (!updatedServers.has(name)) {
108
+ this.manager.removeServer(name);
109
+ }
110
+ }
111
+
112
+ for (const [name, description] of updatedServers) {
113
+ const oldDescription = oldServers.get(name);
114
+ let diff = false;
115
+ try {
116
+ // We know that that the descriptions are actual JSONObjects as we construct them ourselves
117
+ if (!oldDescription || !PreferenceProvider.deepEqual(oldDescription as unknown as JSONObject, description as unknown as JSONObject)) {
118
+ diff = true;
119
+ }
120
+ } catch (e) {
121
+ // In some cases the deepEqual function throws an error, so we fall back to assuming that there is a difference
122
+ // This seems to happen in cases where the objects are structured differently, e.g. whole sub-objects are missing
123
+ console.debug('Failed to compare MCP server descriptions, assuming a difference', e);
124
+ diff = true;
125
+ }
126
+ if (diff) {
127
+ this.manager.addOrUpdateServer(description);
128
+ }
129
+ }
130
+
131
+ this.prevServers = updatedServers;
132
+ }
133
+
134
+ protected syncServers(servers: Map<string, MCPServerDescription>): void {
135
+
136
+ for (const [, description] of servers) {
137
+ this.manager.addOrUpdateServer(description);
138
+ }
139
+
140
+ for (const [name] of this.prevServers) {
141
+ if (!servers.has(name)) {
142
+ this.manager.removeServer(name);
143
+ }
144
+ }
145
+ }
146
+
147
+ protected convertToMap(servers: MCPServersPreference): Map<string, MCPServerDescription> {
148
+ const map = new Map<string, MCPServerDescription>();
149
+ Object.entries(servers).forEach(([name, description]) => {
150
+ map.set(name, {
151
+ name,
152
+ ...description,
153
+ env: description.env || undefined
154
+ });
155
+ });
156
+ return map;
157
+ }
158
+ }
@@ -0,0 +1,35 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { CommandContribution } from '@theia/core';
18
+ import { ContainerModule } from '@theia/core/shared/inversify';
19
+ import { MCPCommandContribution } from './mcp-command-contribution';
20
+ import { FrontendApplicationContribution, PreferenceContribution, RemoteConnectionProvider, ServiceConnectionProvider } from '@theia/core/lib/browser';
21
+ import { MCPServerManager, MCPServerManagerPath } from '../common/mcp-server-manager';
22
+ import { McpServersPreferenceSchema } from './mcp-preferences';
23
+ import { McpFrontendApplicationContribution } from './mcp-frontend-application-contribution';
24
+ import { MCPFrontendService } from './mcp-frontend-service';
25
+
26
+ export default new ContainerModule(bind => {
27
+ bind(PreferenceContribution).toConstantValue({ schema: McpServersPreferenceSchema });
28
+ bind(FrontendApplicationContribution).to(McpFrontendApplicationContribution).inSingletonScope();
29
+ bind(CommandContribution).to(MCPCommandContribution);
30
+ bind(MCPServerManager).toDynamicValue(ctx => {
31
+ const connection = ctx.container.get<ServiceConnectionProvider>(RemoteConnectionProvider);
32
+ return connection.createProxy<MCPServerManager>(MCPServerManagerPath);
33
+ }).inSingletonScope();
34
+ bind(MCPFrontendService).toSelf().inSingletonScope();
35
+ });
@@ -0,0 +1,87 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ import { injectable, inject } from '@theia/core/shared/inversify';
17
+ import { MCPServer, MCPServerManager } from '../common/mcp-server-manager';
18
+ import { ToolInvocationRegistry, ToolRequest } from '@theia/ai-core';
19
+
20
+ @injectable()
21
+ export class MCPFrontendService {
22
+ @inject(MCPServerManager)
23
+ protected readonly mcpServerManager: MCPServerManager;
24
+
25
+ @inject(ToolInvocationRegistry)
26
+ protected readonly toolInvocationRegistry: ToolInvocationRegistry;
27
+
28
+ async startServer(serverName: string): Promise<void> {
29
+ await this.mcpServerManager.startServer(serverName);
30
+ this.registerTools(serverName);
31
+ }
32
+
33
+ async registerToolsForAllStartedServers(): Promise<void> {
34
+ const startedServers = await this.getStartedServers();
35
+ for (const serverName of startedServers) {
36
+ await this.registerTools(serverName);
37
+ }
38
+ }
39
+
40
+ async registerTools(serverName: string): Promise<void> {
41
+ const { tools } = await this.getTools(serverName);
42
+ const toolRequests: ToolRequest[] = tools.map(tool => this.convertToToolRequest(tool, serverName));
43
+ toolRequests.forEach(toolRequest =>
44
+ this.toolInvocationRegistry.registerTool(toolRequest)
45
+ );
46
+ }
47
+
48
+ async stopServer(serverName: string): Promise<void> {
49
+ this.toolInvocationRegistry.unregisterAllTools(`mcp_${serverName}`);
50
+ await this.mcpServerManager.stopServer(serverName);
51
+ }
52
+
53
+ getStartedServers(): Promise<string[]> {
54
+ return this.mcpServerManager.getStartedServers();
55
+ }
56
+
57
+ getServerNames(): Promise<string[]> {
58
+ return this.mcpServerManager.getServerNames();
59
+ }
60
+
61
+ getTools(serverName: string): ReturnType<MCPServer['getTools']> {
62
+ return this.mcpServerManager.getTools(serverName);
63
+ }
64
+
65
+ private convertToToolRequest(tool: Awaited<ReturnType<MCPServerManager['getTools']>>['tools'][number], serverName: string): ToolRequest {
66
+ const id = `mcp_${serverName}_${tool.name}`;
67
+ return {
68
+ id: id,
69
+ name: id,
70
+ providerName: `mcp_${serverName}`,
71
+ parameters: ToolRequest.isToolRequestParameters(tool.inputSchema) ? {
72
+ type: tool.inputSchema.type,
73
+ properties: tool.inputSchema.properties,
74
+ required: tool.inputSchema.required
75
+ } : undefined,
76
+ description: tool.description,
77
+ handler: async (arg_string: string) => {
78
+ try {
79
+ return await this.mcpServerManager.callTool(serverName, tool.name, arg_string);
80
+ } catch (error) {
81
+ console.error(`Error in tool handler for ${tool.name} on MCP server ${serverName}:`, error);
82
+ throw error;
83
+ }
84
+ },
85
+ };
86
+ }
87
+ }
@@ -0,0 +1,90 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { PreferenceSchema } from '@theia/core/lib/browser/preferences/preference-contribution';
18
+
19
+ export const MCP_SERVERS_PREF = 'ai-features.mcp.mcpServers';
20
+
21
+ export const McpServersPreferenceSchema: PreferenceSchema = {
22
+ type: 'object',
23
+ properties: {
24
+ [MCP_SERVERS_PREF]: {
25
+ type: 'object',
26
+ title: 'MCP Servers Configuration',
27
+ markdownDescription: 'Configure MCP servers with command, arguments, optionally environment variables, and autostart.\
28
+ Each server is identified by a unique key, such as "brave-search" or "filesystem".\
29
+ To start a server, use the "MCP: Start MCP Server" command, which enables you to select the desired server.\
30
+ To stop a server, use the "MCP: Stop MCP Server" command.\
31
+ \n\
32
+ Example configuration:\n\
33
+ ```\
34
+ {\n\
35
+ "brave-search": {\n\
36
+ "command": "npx",\n\
37
+ "args": [\n\
38
+ "-y",\n\
39
+ "@modelcontextprotocol/server-brave-search"\n\
40
+ ],\n\
41
+ "env": {\n\
42
+ "BRAVE_API_KEY": "YOUR_API_KEY"\n\
43
+ },\n\
44
+ "autostart": true\n\
45
+ },\n\
46
+ "filesystem": {\n\
47
+ "command": "npx",\n\
48
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/YOUR_USERNAME/Desktop"],\n\
49
+ "env": {\n\
50
+ "CUSTOM_ENV_VAR": "custom-value"\n\
51
+ },\n\
52
+ "autostart": false\n\
53
+ }\n\
54
+ }\n ```',
55
+ additionalProperties: {
56
+ type: 'object',
57
+ properties: {
58
+ command: {
59
+ type: 'string',
60
+ title: 'Command to execute the MCP server',
61
+ markdownDescription: 'The command used to start the MCP server, e.g., "uvx" or "npx".'
62
+ },
63
+ args: {
64
+ type: 'array',
65
+ title: 'Arguments for the command',
66
+ markdownDescription: 'An array of arguments to pass to the command.',
67
+ items: {
68
+ type: 'string'
69
+ }
70
+ },
71
+ env: {
72
+ type: 'object',
73
+ title: 'Environment variables',
74
+ markdownDescription: 'Optional environment variables to set for the server, such as an API key.',
75
+ additionalProperties: {
76
+ type: 'string'
77
+ }
78
+ },
79
+ autostart: {
80
+ type: 'boolean',
81
+ title: 'Autostart',
82
+ markdownDescription: 'Automatically start this server when the frontend starts. Newly added servers are not immediatly auto stated.',
83
+ default: false
84
+ }
85
+ },
86
+ required: ['command', 'args']
87
+ }
88
+ }
89
+ }
90
+ };
@@ -0,0 +1,16 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+ export * from './mcp-server-manager';
@@ -0,0 +1,63 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import type { Client } from '@modelcontextprotocol/sdk/client/index';
18
+
19
+ export interface MCPServer {
20
+ callTool(toolName: string, arg_string: string): ReturnType<Client['callTool']>;
21
+ getTools(): ReturnType<Client['listTools']>;
22
+ }
23
+
24
+ export interface MCPServerManager {
25
+ callTool(serverName: string, toolName: string, arg_string: string): ReturnType<MCPServer['callTool']>;
26
+ removeServer(name: string): void;
27
+ addOrUpdateServer(description: MCPServerDescription): void;
28
+ getTools(serverName: string): ReturnType<MCPServer['getTools']>
29
+ getServerNames(): Promise<string[]>;
30
+ startServer(serverName: string): Promise<void>;
31
+ stopServer(serverName: string): Promise<void>;
32
+ getStartedServers(): Promise<string[]>;
33
+ }
34
+
35
+ export interface MCPServerDescription {
36
+ /**
37
+ * The unique name of the MCP server.
38
+ */
39
+ name: string;
40
+
41
+ /**
42
+ * The command to execute the MCP server.
43
+ */
44
+ command: string;
45
+
46
+ /**
47
+ * An array of arguments to pass to the command.
48
+ */
49
+ args?: string[];
50
+
51
+ /**
52
+ * Optional environment variables to set when starting the server.
53
+ */
54
+ env?: { [key: string]: string };
55
+
56
+ /**
57
+ * Flag indicating whether the server should automatically start when the application starts.
58
+ */
59
+ autostart?: boolean;
60
+ }
61
+
62
+ export const MCPServerManager = Symbol('MCPServerManager');
63
+ export const MCPServerManagerPath = '/services/mcpservermanager';
@@ -0,0 +1,37 @@
1
+ // *****************************************************************************
2
+ // Copyright (C) 2024 EclipseSource GmbH.
3
+ //
4
+ // This program and the accompanying materials are made available under the
5
+ // terms of the Eclipse Public License v. 2.0 which is available at
6
+ // http://www.eclipse.org/legal/epl-2.0.
7
+ //
8
+ // This Source Code may also be made available under the following Secondary
9
+ // Licenses when the conditions for such availability set forth in the Eclipse
10
+ // Public License v. 2.0 are satisfied: GNU General Public License, version 2
11
+ // with the GNU Classpath Exception which is available at
12
+ // https://www.gnu.org/software/classpath/license.html.
13
+ //
14
+ // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
15
+ // *****************************************************************************
16
+
17
+ import { ContainerModule } from '@theia/core/shared/inversify';
18
+ import { ConnectionHandler, RpcConnectionHandler } from '@theia/core';
19
+ import { MCPServerManagerImpl } from './mcp-server-manager-impl';
20
+ import { MCPServerManager, MCPServerManagerPath } from '../common/mcp-server-manager';
21
+ import { ConnectionContainerModule } from '@theia/core/lib/node/messaging/connection-container-module';
22
+
23
+ // We use a connection module to handle AI services separately for each frontend.
24
+ const mcpConnectionModule = ConnectionContainerModule.create(({ bind, bindBackendService, bindFrontendService }) => {
25
+ bind(MCPServerManager).to(MCPServerManagerImpl).inSingletonScope();
26
+ bind(ConnectionHandler).toDynamicValue(ctx => new RpcConnectionHandler(
27
+ MCPServerManagerPath,
28
+ () => {
29
+ const service = ctx.container.get<MCPServerManager>(MCPServerManager);
30
+ return service;
31
+ }
32
+ )).inSingletonScope();
33
+ });
34
+
35
+ export default new ContainerModule(bind => {
36
+ bind(ConnectionContainerModule).toConstantValue(mcpConnectionModule);
37
+ });