From 7effc86df2320c6a559a9607e0823c9dc915f311 Mon Sep 17 00:00:00 2001 From: ci-bot Date: Tue, 28 Oct 2025 15:16:59 +0100 Subject: [PATCH] add mcp tutorial endpoint --- .../src/remix-mcp-server/RemixMCPServer.ts | 12 ++++ .../handlers/TutorialsHandler.ts | 64 ++++++++++++++++++ .../src/remix-mcp-server/index.ts | 1 + .../providers/TutorialsResourceProvider.ts | 66 +++++++++++++++++++ .../remix-mcp-server/types/mcpResources.ts | 1 + .../src/lib/solidity-scan.ts | 2 +- 6 files changed, 145 insertions(+), 1 deletion(-) create mode 100644 libs/remix-ai-core/src/remix-mcp-server/handlers/TutorialsHandler.ts create mode 100644 libs/remix-ai-core/src/remix-mcp-server/providers/TutorialsResourceProvider.ts diff --git a/libs/remix-ai-core/src/remix-mcp-server/RemixMCPServer.ts b/libs/remix-ai-core/src/remix-mcp-server/RemixMCPServer.ts index 2becc6c0b50..68bbdc0a0ca 100644 --- a/libs/remix-ai-core/src/remix-mcp-server/RemixMCPServer.ts +++ b/libs/remix-ai-core/src/remix-mcp-server/RemixMCPServer.ts @@ -31,11 +31,13 @@ import { createFileManagementTools } from './handlers/FileManagementHandler'; import { createDeploymentTools } from './handlers/DeploymentHandler'; import { createDebuggingTools } from './handlers/DebuggingHandler'; import { createCodeAnalysisTools } from './handlers/CodeAnalysisHandler'; +import { createTutorialsTools } from './handlers/TutorialsHandler'; // Import resource providers import { ProjectResourceProvider } from './providers/ProjectResourceProvider'; import { CompilationResourceProvider } from './providers/CompilationResourceProvider'; import { DeploymentResourceProvider } from './providers/DeploymentResourceProvider'; +import { TutorialsResourceProvider } from './providers/TutorialsResourceProvider'; /** * Main Remix MCP Server implementation @@ -475,6 +477,11 @@ export class RemixMCPServer extends EventEmitter implements IRemixMCPServer { this._tools.registerBatch(codeAnalysisTools); console.log(`Registered ${codeAnalysisTools.length} code analysis tools`, 'info'); + // Register debugging tools + const tutorialTools = createTutorialsTools(); + this._tools.registerBatch(tutorialTools); + console.log(`Registered ${tutorialTools.length} code analysis tools`, 'info'); + const totalTools = this._tools.list().length; console.log(`Total tools registered: ${totalTools}`, 'info'); @@ -507,6 +514,11 @@ export class RemixMCPServer extends EventEmitter implements IRemixMCPServer { this._resources.register(deploymentProvider); console.log(`Registered deployment resource provider: ${deploymentProvider.name}`, 'info'); + // Register deployment resource provider + const tutorialsProvider = new TutorialsResourceProvider(this._plugin); + this._resources.register(tutorialsProvider); + console.log(`Registered tutorials resource provider: ${tutorialsProvider.name}`, 'info'); + const totalProviders = this._resources.list().length; console.log(`Total resource providers registered: ${totalProviders}`, 'info'); diff --git a/libs/remix-ai-core/src/remix-mcp-server/handlers/TutorialsHandler.ts b/libs/remix-ai-core/src/remix-mcp-server/handlers/TutorialsHandler.ts new file mode 100644 index 00000000000..b09c8e20fb4 --- /dev/null +++ b/libs/remix-ai-core/src/remix-mcp-server/handlers/TutorialsHandler.ts @@ -0,0 +1,64 @@ +/** + * Code Analysis Tool Handlers for Remix MCP Server + */ + +import { IMCPToolResult } from '../../types/mcp'; +import { BaseToolHandler } from '../registry/RemixToolRegistry'; +import { + ToolCategory, + RemixToolDefinition +} from '../types/mcpTools'; +import { Plugin } from '@remixproject/engine'; + +/** + * Solidity Scan Tool Handler + * Analyzes Solidity code for security vulnerabilities and code quality issues + */ +export class TutorialsHandler extends BaseToolHandler { + name = 'tutorials'; + description = 'Use learneth to start a tutorial'; + inputSchema = { + type: 'object', + properties: { + tutorialId: { + type: 'string', + description: 'id of the tutorial to start' + } + }, + required: ['tutorialId'] + }; + + getPermissions(): string[] { + return ['tutorial:sstart']; + } + + validate(args: { filePath: string }): boolean | string { + const required = this.validateRequired(args, ['tutorialId']); + if (required !== true) return required + return true; + } + + async execute(args: { tutorialId: string }, plugin: Plugin): Promise { + try { + plugin.call('LearnEth', 'startTutorial', "remix-project-org/remix-workshops", "master", args.tutorialId) + } catch (error) { + return this.createErrorResult(`Starting tutorial failed: ${error.message}`); + } + } +} + +/** + * Create code analysis tool definitions + */ +export function createTutorialsTools(): RemixToolDefinition[] { + return [ + { + name: 'tutorials', + description: 'Use learneth to start a tutorial', + inputSchema: new TutorialsHandler().inputSchema, + category: ToolCategory.ANALYSIS, + permissions: ['analysis:scan', 'file:read'], + handler: new TutorialsHandler() + } + ]; +} diff --git a/libs/remix-ai-core/src/remix-mcp-server/index.ts b/libs/remix-ai-core/src/remix-mcp-server/index.ts index 512fd12d44f..8e0efd957eb 100644 --- a/libs/remix-ai-core/src/remix-mcp-server/index.ts +++ b/libs/remix-ai-core/src/remix-mcp-server/index.ts @@ -22,6 +22,7 @@ export { createCodeAnalysisTools } from './handlers/CodeAnalysisHandler'; export { ProjectResourceProvider } from './providers/ProjectResourceProvider'; export { CompilationResourceProvider } from './providers/CompilationResourceProvider'; export { DeploymentResourceProvider } from './providers/DeploymentResourceProvider'; +export { TutorialsResourceProvider } from './providers/TutorialsResourceProvider'; // Middleware export { diff --git a/libs/remix-ai-core/src/remix-mcp-server/providers/TutorialsResourceProvider.ts b/libs/remix-ai-core/src/remix-mcp-server/providers/TutorialsResourceProvider.ts new file mode 100644 index 00000000000..9706bf45289 --- /dev/null +++ b/libs/remix-ai-core/src/remix-mcp-server/providers/TutorialsResourceProvider.ts @@ -0,0 +1,66 @@ +/** + * Compilation Resource Provider - Provides access to compilation results and artifacts + */ + +import axios from 'axios'; +import { Plugin } from '@remixproject/engine'; +import { IMCPResource, IMCPResourceContent } from '../../types/mcp'; +import { BaseResourceProvider } from '../registry/RemixResourceProviderRegistry'; +import { ResourceCategory } from '../types/mcpResources'; + +export class TutorialsResourceProvider extends BaseResourceProvider { + name = 'tutorials'; + description = 'Provides access to a list of tutorials and their details'; + private _plugin + + constructor (plugin){ + super() + this._plugin = plugin + } + async getResources(plugin: Plugin): Promise { + const resources: IMCPResource[] = []; + + try { + // Add tutorial resources + resources.push( + this.createResource( + 'tutorials://list', + 'Tutorials', + 'List of tutorials for learning web3, solidity, blockchain and smart contract development', + 'application/json', + { + category: ResourceCategory.TUTORIALS, + tags: ['solidity', 'web3', 'tutorial'], + priority: 9 + } + ) + ) + } catch (error) { + console.warn('Failed to get tutorials resources:', error); + } + + return resources; + } + + async getResourceContent(uri: string, plugin: Plugin): Promise { + if (uri === 'tutorials://list') { + return this.getTutorialsList(plugin); + } + + throw new Error(`Unsupported compilation resource URI: ${uri}`); + } + + canHandle(uri: string): boolean { + return uri.startsWith('tutorials://'); + } + + private async getTutorialsList(plugin: Plugin): Promise { + try { + const tutorials = await axios('https://raw.githubusercontent.com/remix-project-org/remix-workshops/refs/heads/json_desc/config-properties.json') + console.log(tutorials) + return this.createJsonContent('tutorials://list', tutorials); + } catch (error) { + return this.createTextContent('tutorials://list', `Error getting tutorials: ${error.message}`); + } + } +} \ No newline at end of file diff --git a/libs/remix-ai-core/src/remix-mcp-server/types/mcpResources.ts b/libs/remix-ai-core/src/remix-mcp-server/types/mcpResources.ts index 0ce6e7795bb..7504bb37811 100644 --- a/libs/remix-ai-core/src/remix-mcp-server/types/mcpResources.ts +++ b/libs/remix-ai-core/src/remix-mcp-server/types/mcpResources.ts @@ -24,6 +24,7 @@ export enum ResourceCategory { PROJECT_FILES = 'project_files', CODE = 'CODE', COMPILATION_RESULTS = 'compilation_results', + TUTORIALS = 'tutorials', DEPLOYMENT_DATA = 'deployment_data', DEBUG_SESSIONS = 'debug_sessions', ANALYSIS_REPORTS = 'analysis_reports', diff --git a/libs/remix-core-plugin/src/lib/solidity-scan.ts b/libs/remix-core-plugin/src/lib/solidity-scan.ts index 743d3625c8c..44f329cdf21 100644 --- a/libs/remix-core-plugin/src/lib/solidity-scan.ts +++ b/libs/remix-core-plugin/src/lib/solidity-scan.ts @@ -2,7 +2,7 @@ import axios from 'axios' import { endpointUrls } from '@remix-endpoints-helper' import { ScanReport } from '@remix-ui/helper' -const _paq = (window._paq = window._paq || []) +const _paq = ((window as any)._paq = (window as any)._paq || []) /** * Core function to perform Solidity scan and return the scan report