Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 15 additions & 9 deletions apps/rush-mcp-server/src/pluginFramework/RushMcpPluginLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ export interface IJsonRushMcpPlugin {
* @rushstack/mcp-server will ensure this folder is installed before loading the plugin.
*/
autoinstaller: string;

/**
* The name of the plugin. This is used to identify the plugin in the MCP server.
*/
pluginName: string;
}

/**
Expand Down Expand Up @@ -85,6 +80,10 @@ export class RushMcpPluginLoader {
this._mcpServer = mcpServer;
}

private static _formatError(e: Error): string {
return e.stack ?? RushMcpPluginLoader._formatError(e);
}

public async loadAsync(): Promise<void> {
const rushMcpFilePath: string = path.join(
this._rushWorkspacePath,
Expand Down Expand Up @@ -151,7 +150,7 @@ export class RushMcpPluginLoader {
const mcpPluginSchema: JsonSchema = await JsonSchema.fromFile(mcpPluginSchemaFilePath);
const rushMcpPluginOptionsFilePath: string = path.resolve(
this._rushWorkspacePath,
`common/config/rush-mcp/${jsonMcpPlugin.pluginName}.json`
`common/config/rush-mcp/${jsonManifest.pluginName}.json`
);
// Example: /path/to/my-repo/common/config/rush-mcp/rush-mcp-example-plugin.json
rushMcpPluginOptions = await JsonFile.loadAndValidateAsync(
Expand All @@ -169,7 +168,10 @@ export class RushMcpPluginLoader {
}
pluginFactory = entryPointModule.default;
} catch (e) {
throw new Error(`Unable to load plugin entry point at ${fullEntryPointPath}: ` + e.toString());
throw new Error(
`Unable to load plugin entry point at ${fullEntryPointPath}:\n` +
RushMcpPluginLoader._formatError(e)
);
}

const session: RushMcpPluginSessionInternal = new RushMcpPluginSessionInternal(this._mcpServer);
Expand All @@ -178,14 +180,18 @@ export class RushMcpPluginLoader {
try {
plugin = pluginFactory(session, rushMcpPluginOptions);
} catch (e) {
throw new Error(`Error invoking entry point for plugin ${jsonManifest.pluginName}:` + e.toString());
throw new Error(
`Error invoking entry point for plugin ${jsonManifest.pluginName}:\n` +
RushMcpPluginLoader._formatError(e)
);
}

try {
await plugin.onInitializeAsync();
} catch (e) {
throw new Error(
`Error occurred in onInitializeAsync() for plugin ${jsonManifest.pluginName}:` + e.toString()
`Error occurred in onInitializeAsync() for plugin ${jsonManifest.pluginName}:\n` +
RushMcpPluginLoader._formatError(e)
);
}
}
Expand Down
4 changes: 0 additions & 4 deletions apps/rush-mcp-server/src/schemas/rush-mcp.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,6 @@
"autoinstaller": {
"type": "string",
"description": "The name of a Rush autoinstaller with this package as its dependency."
},
"pluginName": {
"type": "string",
"description": "The name of the plugin. This is used to identify the plugin in the MCP server."
}
},
"required": ["packageName", "autoinstaller"],
Expand Down
23 changes: 21 additions & 2 deletions apps/rush-mcp-server/src/start.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,37 @@
// Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license.
// See LICENSE in the project root for license information.

import * as path from 'path';
import * as process from 'process';
import { FileSystem } from '@rushstack/node-core-library';
import { RushSdkLoader } from '@rushstack/rush-sdk/loader';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';

import { log } from './utilities/log';
import { RushMCPServer } from './server';
import type { RushMCPServer } from './server';

const main = async (): Promise<void> => {
const rushWorkspacePath: string | undefined = process.argv[2];
if (!rushWorkspacePath) {
throw new Error('Please provide workspace root path as the first argument');
}

const server: RushMCPServer = new RushMCPServer(rushWorkspacePath);
const rushWorkspaceFullPath: string = path.resolve(rushWorkspacePath);

if (!(await FileSystem.existsAsync(rushWorkspaceFullPath))) {
throw new Error(
'The specified workspace root path does not exist:\n ' + JSON.stringify(rushWorkspacePath)
);
}

// Load rush-sdk from the specified repository
await RushSdkLoader.loadAsync({
rushJsonSearchFolder: rushWorkspaceFullPath
});

const RushMCPServerClass: typeof RushMCPServer = (await import('./server')).RushMCPServer;

const server: RushMCPServer = new RushMCPServerClass(rushWorkspaceFullPath);
await server.startAsync();
const transport: StdioServerTransport = new StdioServerTransport();
await server.connect(transport);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "State Capital Map",
"type": "object",
"required": ["capitalsByState"],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@rushstack/mcp-server",
"comment": "Fix some errors when loading plugins",
"type": "patch"
}
],
"packageName": "@rushstack/mcp-server"
}