# Directory Structure
```
├── .editorconfig
├── .gitignore
├── .prettierrc
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── src
│ └── index.ts
├── tsconfig.json
├── vitest.config.mts
├── worker-configuration.d.ts
└── wrangler.jsonc
```
# Files
--------------------------------------------------------------------------------
/.prettierrc:
--------------------------------------------------------------------------------
```
{
"printWidth": 140,
"singleQuote": true,
"semi": true,
"useTabs": true
}
```
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
```
# http://editorconfig.org
root = true
[*]
indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.yml]
indent_style = space
```
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
# Logs
logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Runtime data
pids
_.pid
_.seed
\*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
\*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
\*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
\*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
.cache
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.\*
# wrangler project
.dev.vars
.wrangler/
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# Code Explainer MCP
A Cloudflare Worker that serves as an MCP (Model Context Protocol) server for code explanation. It analyzes and explains code with a comprehensive breakdown of structure and functionality.

## Features
- **Architecture Diagram**: Generates an ASCII diagram showing the overall structure, relationships between components, and data flow.
- **Core Functionality Analysis**: Identifies and explains the primary purpose of the code based on pattern recognition.
- **Component Breakdown**: Lists all main classes and functions with brief descriptions of their roles.
- **Multi-language Support**: Analyzes code in various programming languages including JavaScript, TypeScript, Python, Java, C#, and more.
- **JSDoc/Docstring Recognition**: Extracts and utilizes existing documentation in the code.
- **Secure API**: Bearer token authentication to secure your endpoints.
## How It Works
The Code Explainer analyzes source code using a combination of techniques:
1. **Pattern Recognition**: Identifies code structures and common patterns
2. **Relationship Analysis**: Maps dependencies between components
3. **Documentation Extraction**: Prioritizes existing documentation comments
4. **Architecture Visualization**: Creates ASCII diagrams of the code structure
5. **Component Description**: Provides semantic descriptions of functions and classes
All processing happens within the Cloudflare Worker with no external dependencies.
## Installation
### Prerequisites
- [Node.js](https://nodejs.org/) (version 12 or higher)
- [Wrangler](https://developers.cloudflare.com/workers/wrangler/get-started/) (Cloudflare Workers CLI)
- A Cloudflare account
### Setup
1. Clone this repository:
```bash
git clone https://github.com/BillDuke13/code-explainer-mcp.git
cd code-explainer-mcp
```
2. Install dependencies:
```bash
npm install
```
3. Configure your secret key:
- Edit `wrangler.jsonc` and replace `YOUR_SECRET_KEY_HERE` with your chosen secret key, or
- Use Cloudflare secrets (recommended for production):
```bash
wrangler secret put SHARED_SECRET
```
4. Deploy to Cloudflare Workers:
```bash
npm run deploy
```
## Usage
### API Endpoint
Send a POST request to your worker URL with the following JSON body:
```json
{
"method": "explainCode",
"params": ["your code here", "programming language"]
}
```
Include the Authorization header with your secret key:
```
Authorization: Bearer YOUR_SECRET_KEY_HERE
```
### Response Format
The response will be a JSON object with a `result` field containing the code analysis:
```json
{
"result": "# Code Analysis for JavaScript Code\n\n## Architecture Diagram\n...\n\n## Core Functionality\n..."
}
```
### Example Usage
#### JavaScript (Browser)
```javascript
async function explainCode(code, language) {
const response = await fetch('https://your-worker-url.workers.dev', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_SECRET_KEY_HERE',
},
body: JSON.stringify({
method: "explainCode",
params: [code, language]
}),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data.result;
}
// Example usage
const jsCode = `function add(a, b) { return a + b; }`;
explainCode(jsCode, "javascript")
.then(explanation => console.log(explanation))
.catch(error => console.error('Error:', error));
```
#### Python (Requests)
```python
import requests
import json
def explain_code(code, language, api_url, secret_key):
headers = {
'Content-Type': 'application/json',
'Authorization': f'Bearer {secret_key}'
}
payload = {
'method': 'explainCode',
'params': [code, language]
}
response = requests.post(api_url, headers=headers, json=payload)
response.raise_for_status()
return response.json()['result']
# Example usage
code = "def hello(): print('Hello, world!')"
explanation = explain_code(code, "python", "https://your-worker-url.workers.dev", "YOUR_SECRET_KEY_HERE")
print(explanation)
```
#### Node.js (Axios)
```javascript
const axios = require('axios');
async function explainCode(code, language) {
try {
const response = await axios.post('https://your-worker-url.workers.dev', {
method: 'explainCode',
params: [code, language]
}, {
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_SECRET_KEY_HERE'
}
});
return response.data.result;
} catch (error) {
console.error('Error:', error.response ? error.response.data : error.message);
throw error;
}
}
// Example usage
const codeToAnalyze = `
class Person {
constructor(name) {
this.name = name;
}
sayHello() {
return \`Hello, my name is \${this.name}\`;
}
}
`;
explainCode(codeToAnalyze, 'javascript')
.then(explanation => console.log(explanation))
.catch(err => console.error('Failed to explain code:', err));
```
## Local Development
1. Clone the repository and install dependencies:
```bash
git clone https://github.com/BillDuke13/code-explainer-mcp.git
cd code-explainer-mcp
npm install
```
2. Run the development server:
```bash
wrangler dev
```
3. Test the endpoint locally:
```bash
curl -X POST http://localhost:8787 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_SECRET_KEY_HERE" \
-d '{"method":"explainCode","params":["function hello() { return \"Hello World\"; }","javascript"]}'
```
### Development Guidelines
- Follow TypeScript best practices
- Add comments for complex logic
- Update documentation for public API changes
- Add tests for new features
## Security
- The API is secured with Bearer token authentication
- Use environment secrets for storing the shared secret in production
- Do not commit your actual secret key to version control
- Rate limiting is recommended for production deployments
## License
This project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.
```
--------------------------------------------------------------------------------
/worker-configuration.d.ts:
--------------------------------------------------------------------------------
```typescript
// Generated by Wrangler
// After adding bindings to `wrangler.jsonc`, regenerate this interface via `npm run cf-typegen`
interface Env {
SHARED_SECRET: string;
}
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
{
"name": "code-explainer-mcp",
"version": "0.0.0",
"private": true,
"scripts": {
"deploy": "workers-mcp docgen src/index.ts && wrangler deploy",
"dev": "wrangler dev",
"start": "wrangler dev",
"test": "vitest",
"cf-typegen": "wrangler types"
},
"devDependencies": {
"@cloudflare/vitest-pool-workers": "^0.6.4",
"@cloudflare/workers-types": "^4.20250224.0",
"typescript": "^5.5.2",
"vitest": "~2.1.9",
"wrangler": "^3.111.0"
},
"dependencies": {
"workers-mcp": "^0.0.13"
}
}
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
"target": "es2021",
/* Specify a set of bundled library declaration files that describe the target runtime environment. */
"lib": ["es2021"],
/* Specify what JSX code is generated. */
"jsx": "react-jsx",
/* Specify what module code is generated. */
"module": "es2022",
/* Specify how TypeScript looks up a file from a given module specifier. */
"moduleResolution": "Bundler",
/* Specify type package names to be included without being referenced in a source file. */
"types": [
"@cloudflare/workers-types/2023-07-01"
],
/* Enable importing .json files */
"resolveJsonModule": true,
/* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */
"allowJs": true,
/* Enable error reporting in type-checked JavaScript files. */
"checkJs": false,
/* Disable emitting files from a compilation. */
"noEmit": true,
/* Ensure that each file can be safely transpiled without relying on other imports. */
"isolatedModules": true,
/* Allow 'import x from y' when a module doesn't have a default export. */
"allowSyntheticDefaultImports": true,
/* Ensure that casing is correct in imports. */
"forceConsistentCasingInFileNames": true,
/* Enable all strict type-checking options. */
"strict": true,
/* Skip type checking all .d.ts files. */
"skipLibCheck": true
},
"exclude": ["test"],
"include": ["worker-configuration.d.ts", "src/**/*.ts"]
}
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
/**
* Code Explainer MCP - A Cloudflare Worker that analyzes and explains code
*/
// Define the environment interface
interface Env {
SHARED_SECRET: string;
}
/**
* Analyzes and explains code with a comprehensive breakdown of structure and functionality.
*
* @param code {string} The source code to analyze
* @param programming_language {string} The programming language of the code
* @return {string} A detailed analysis of the code
*/
async function explainCode(code: string, programming_language: string): Promise<string> {
// Create a basic architecture diagram (ASCII)
const architectureDiagram = generateArchitectureDiagram(code, programming_language);
// Extract core functionality
const coreFunctionality = extractCoreFunctionality(code, programming_language);
// Extract main classes and functions
const { mainClasses, mainFunctions } = extractComponents(code, programming_language);
// Format the response according to the prompt template
const response = `
# Code Analysis for ${programming_language} Code
## Architecture Diagram
\`\`\`
${architectureDiagram}
\`\`\`
## Core Functionality
${coreFunctionality}
## Main Classes:
${mainClasses.map(c => `- ${c.name}: ${c.description}`).join('\n')}
## Main Functions:
${mainFunctions.map(f => `- ${f.name}: ${f.description}`).join('\n')}
Would you like me to explain all the functions and classes in detail? Or are you more interested in a specific part?
`;
return response;
}
/**
* Generates a comprehensive ASCII architecture diagram based on code analysis.
*
* @param code {string} The source code to analyze
* @param programming_language {string} The programming language of the code
* @return {string} An ASCII diagram representing the code architecture
*/
function generateArchitectureDiagram(code: string, programming_language: string): string {
// Detect language-specific patterns
let classRegex, functionRegex, methodRegex, importRegex;
switch(programming_language.toLowerCase()) {
case 'javascript':
case 'typescript':
case 'js':
case 'ts':
classRegex = /class\s+(\w+)(?:\s+extends\s+(\w+))?/g;
functionRegex = /function\s+(\w+)/g;
methodRegex = /(\w+)\s*\([^)]*\)\s*{/g;
importRegex = /import\s+(?:{[^}]*}|[^{;]*)(?:\s+from)?\s+['"]([^'"]+)['"]/g;
break;
case 'python':
classRegex = /class\s+(\w+)(?:\(([^)]+)\))?:/g;
functionRegex = /def\s+(\w+)/g;
methodRegex = /def\s+(\w+)\s*\(self,?[^)]*\):/g;
importRegex = /(?:from\s+(\w+(?:\.\w+)*)\s+import|import\s+(\w+(?:\.\w+)*))/g;
break;
case 'java':
case 'c#':
case 'csharp':
classRegex = /class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([^{]+))?/g;
functionRegex = /(?:public|private|protected|static)?\s+\w+\s+(\w+)\s*\([^)]*\)\s*{/g;
methodRegex = /(?:public|private|protected|static)?\s+\w+\s+(\w+)\s*\([^)]*\)\s*{/g;
importRegex = /import\s+([^;]+);/g;
break;
default:
// Generic patterns for other languages
classRegex = /class\s+(\w+)/g;
functionRegex = /function\s+(\w+)|def\s+(\w+)|(\w+)\s*\([^)]*\)\s*{/g;
methodRegex = /(\w+)\s*\([^)]*\)\s*{|def\s+(\w+)/g;
importRegex = /import|require|include|using/g;
}
// Extract components
let match;
// Reset regex lastIndex
classRegex.lastIndex = 0;
functionRegex.lastIndex = 0;
importRegex.lastIndex = 0;
// Extract classes with inheritance
interface ClassInfo {
name: string;
parent: string | null;
index: number;
}
const classes: ClassInfo[] = [];
while ((match = classRegex.exec(code)) !== null) {
classes.push({
name: match[1],
parent: match[2] || null,
index: match.index
});
}
// Extract functions
interface FunctionInfo {
name: string;
index: number;
}
const functions: FunctionInfo[] = [];
while ((match = functionRegex.exec(code)) !== null) {
// Skip if inside a class
let isInsideClass = false;
for (const cls of classes) {
const classCode = extractBlock(code, cls.index);
if (match.index > cls.index && match.index < cls.index + classCode.length) {
isInsideClass = true;
break;
}
}
if (!isInsideClass) {
functions.push({
name: match[1] || match[2] || match[3],
index: match.index
});
}
}
// Extract imports/dependencies
const imports: string[] = [];
while ((match = importRegex.exec(code)) !== null) {
imports.push(match[1] || match[2] || "external dependency");
}
// Analyze relationships between components
interface Relationship {
from: string;
to: string;
type: string;
}
const relationships: Relationship[] = [];
// Check for class inheritance
for (const cls of classes) {
if (cls.parent) {
relationships.push({
from: cls.name,
to: cls.parent,
type: 'inherits'
});
}
}
// Check for function calls
for (const func of functions) {
const functionCode = extractBlock(code, func.index);
// Check if this function calls other functions
for (const otherFunc of functions) {
if (func.name !== otherFunc.name &&
functionCode.includes(`${otherFunc.name}(`)) {
relationships.push({
from: func.name,
to: otherFunc.name,
type: 'calls'
});
}
}
}
// Generate the diagram
let diagram = '';
// Add header
diagram += '+----------------------+\n';
diagram += '| Code Structure |\n';
diagram += '+----------------------+\n';
// Add imports/dependencies if found
if (imports.length > 0) {
diagram += '\n Dependencies:\n';
for (let i = 0; i < Math.min(imports.length, 3); i++) {
diagram += ` [${imports[i]}]\n`;
}
if (imports.length > 3) {
diagram += ' [...more dependencies...]\n';
}
diagram += '\n |\n v\n';
}
// Add classes with inheritance
if (classes.length > 0) {
diagram += '\n Classes:\n';
// First add parent classes
const parentClasses = classes.filter(c => !c.parent);
for (const cls of parentClasses) {
diagram += ` +------------------+\n`;
diagram += ` | ${cls.name.padEnd(14)} |\n`;
diagram += ` +------------------+\n`;
// Add child classes
const childClasses = classes.filter(c => c.parent === cls.name);
if (childClasses.length > 0) {
for (let i = 0; i < childClasses.length; i++) {
const isLast = i === childClasses.length - 1;
diagram += ` ${isLast ? '└' : '├'}──extends──┐\n`;
diagram += ` +------------------+\n`;
diagram += ` | ${childClasses[i].name.padEnd(14)} |\n`;
diagram += ` +------------------+\n`;
}
}
diagram += '\n';
}
// Add standalone classes (no inheritance)
const standaloneClasses = classes.filter(c => !c.parent && !classes.some(other => other.parent === c.name));
if (standaloneClasses.length > 0) {
for (const cls of standaloneClasses) {
diagram += ` +------------------+\n`;
diagram += ` | ${cls.name.padEnd(14)} |\n`;
diagram += ` +------------------+\n`;
}
}
}
// Add functions and their relationships
if (functions.length > 0) {
diagram += '\n Functions:\n';
// Group functions by relationships
const processedFunctions = new Set();
// First process functions that call other functions
for (const rel of relationships.filter(r => r.type === 'calls')) {
if (!processedFunctions.has(rel.from)) {
diagram += ` [${rel.from}] ──calls──> [${rel.to}]\n`;
processedFunctions.add(rel.from);
processedFunctions.add(rel.to);
}
}
// Then add remaining functions
for (const func of functions) {
if (!processedFunctions.has(func.name)) {
diagram += ` [${func.name}]\n`;
processedFunctions.add(func.name);
}
}
}
// If no classes or functions found, show generic structure
if (classes.length === 0 && functions.length === 0) {
diagram += '\n +------------------+\n';
diagram += ' | Implementation |\n';
diagram += ' +------------------+\n';
}
return diagram;
}
/**
* Extracts and summarizes the core functionality of the code.
*
* @param code {string} The source code to analyze
* @param programming_language {string} The programming language of the code
* @return {string} A description of the core functionality
*/
function extractCoreFunctionality(code: string, programming_language: string): string {
// Define language-specific patterns
const patterns: Record<string, RegExp[]> = {
network: [
/fetch\s*\(/i,
/http/i,
/request/i,
/api/i,
/url/i,
/endpoint/i
],
ui: [
/render/i,
/component/i,
/view/i,
/display/i,
/ui/i,
/interface/i,
/dom/i
],
dataProcessing: [
/map\s*\(/i,
/filter\s*\(/i,
/reduce\s*\(/i,
/transform/i,
/convert/i,
/parse/i
],
authentication: [
/auth/i,
/login/i,
/password/i,
/credential/i,
/token/i,
/permission/i
],
database: [
/database/i,
/db\./i,
/query/i,
/sql/i,
/mongo/i,
/store/i,
/save/i,
/repository/i
],
testing: [
/test/i,
/assert/i,
/expect/i,
/mock/i,
/spec/i
],
algorithm: [
/algorithm/i,
/sort/i,
/search/i,
/calculate/i,
/compute/i
],
fileSystem: [
/file/i,
/read/i,
/write/i,
/path/i,
/directory/i,
/folder/i
]
};
// Add language-specific patterns
switch(programming_language.toLowerCase()) {
case 'javascript':
case 'typescript':
case 'js':
case 'ts':
patterns.ui.push(/react/i, /angular/i, /vue/i, /component/i, /jsx/i, /tsx/i);
patterns.network.push(/axios/i, /fetch/i, /xhr/i);
patterns.database.push(/mongoose/i, /sequelize/i, /typeorm/i);
break;
case 'python':
patterns.ui.push(/flask/i, /django/i, /template/i);
patterns.network.push(/requests/i, /urllib/i);
patterns.database.push(/sqlalchemy/i, /django\.db/i, /cursor/i);
break;
case 'java':
patterns.ui.push(/swing/i, /javafx/i, /awt/i);
patterns.network.push(/httpclient/i, /urlconnection/i);
patterns.database.push(/jdbc/i, /repository/i, /entity/i);
break;
case 'c#':
case 'csharp':
patterns.ui.push(/wpf/i, /xaml/i, /winforms/i);
patterns.network.push(/httpclient/i, /webclient/i);
patterns.database.push(/entity\s*framework/i, /dbcontext/i);
break;
}
// Check for patterns in the code
const matches: Record<string, boolean> = {
network: false,
ui: false,
dataProcessing: false,
authentication: false,
database: false,
testing: false,
algorithm: false,
fileSystem: false
};
// Count matches for each category
const matchCounts: Record<string, number> = {};
for (const category in patterns) {
matchCounts[category] = 0;
for (const pattern of patterns[category]) {
if (pattern.test(code)) {
matchCounts[category]++;
matches[category] = true;
}
}
}
// Determine primary and secondary purposes based on match counts
const sortedCategories = Object.entries(matchCounts)
.sort((a, b) => b[1] - a[1])
.filter(entry => entry[1] > 0)
.map(entry => entry[0]);
const primaryPurpose = sortedCategories[0];
const secondaryPurpose = sortedCategories[1];
// Generate description
let functionality = 'This code appears to ';
if (!primaryPurpose) {
functionality += 'provide general utility functions or core logic for the application.';
return functionality;
}
// Primary purpose description
switch(primaryPurpose) {
case 'ui':
functionality += 'implement a user interface ';
if (matches.network) {
functionality += 'that communicates with external services. ';
} else if (matches.database) {
functionality += 'that interacts with a database. ';
} else {
functionality += 'for displaying and interacting with data. ';
}
break;
case 'network':
functionality += 'handle network communication, ';
if (matches.api) {
functionality += 'likely serving as an API or service layer. ';
} else {
functionality += 'facilitating data exchange with external systems. ';
}
break;
case 'dataProcessing':
functionality += 'process and transform data, ';
if (matches.algorithm) {
functionality += 'implementing specific algorithms for data manipulation. ';
} else {
functionality += 'implementing business logic or data transformation. ';
}
break;
case 'database':
functionality += 'interact with a database, ';
if (matches.dataProcessing) {
functionality += 'performing data operations and transformations. ';
} else {
functionality += 'managing data persistence and retrieval. ';
}
break;
case 'authentication':
functionality += 'handle authentication and authorization, ';
if (matches.ui) {
functionality += 'providing secure user access to the interface. ';
} else if (matches.network) {
functionality += 'securing API endpoints or network resources. ';
} else {
functionality += 'managing user credentials and permissions. ';
}
break;
case 'testing':
functionality += 'implement tests for ';
if (matches.ui) {
functionality += 'user interface components. ';
} else if (matches.network) {
functionality += 'network communication. ';
} else if (matches.database) {
functionality += 'database operations. ';
} else {
functionality += 'application functionality. ';
}
break;
case 'algorithm':
functionality += 'implement specific algorithms ';
if (matches.dataProcessing) {
functionality += 'for data processing and transformation. ';
} else {
functionality += 'to solve computational problems. ';
}
break;
case 'fileSystem':
functionality += 'handle file system operations, ';
if (matches.dataProcessing) {
functionality += 'processing file data. ';
} else {
functionality += 'managing file reading, writing, or organization. ';
}
break;
default:
functionality += 'provide utility functions or core logic for the application. ';
}
// Add secondary purpose if available
if (secondaryPurpose && matchCounts[secondaryPurpose] > 1) {
functionality += 'It also includes functionality for ';
switch(secondaryPurpose) {
case 'ui':
functionality += 'user interface presentation';
break;
case 'network':
functionality += 'network communication';
break;
case 'dataProcessing':
functionality += 'data processing and transformation';
break;
case 'database':
functionality += 'database interaction';
break;
case 'authentication':
functionality += 'authentication and security';
break;
case 'testing':
functionality += 'testing and validation';
break;
case 'algorithm':
functionality += 'algorithmic computation';
break;
case 'fileSystem':
functionality += 'file system operations';
break;
}
functionality += '.';
}
return functionality;
}
/**
* Extracts main classes and functions from the code.
*
* @param code {string} The source code to analyze
* @param programming_language {string} The programming language of the code
* @return {Object} Object containing arrays of main classes and functions with descriptions
*/
function extractComponents(code: string, programming_language: string): {
mainClasses: Array<{name: string, description: string}>,
mainFunctions: Array<{name: string, description: string}>
} {
const mainClasses: Array<{name: string, description: string}> = [];
const mainFunctions: Array<{name: string, description: string}> = [];
// Simple regex to find class names
const classRegex = /class\s+(\w+)/g;
let classMatch;
while ((classMatch = classRegex.exec(code)) !== null) {
const className = classMatch[1];
const classCode = extractBlock(code, classMatch.index);
const description = generateComponentDescription(classCode, 'class');
mainClasses.push({ name: className, description });
}
// Simple regex to find function names
const functionRegex = /function\s+(\w+)/g;
let functionMatch;
while ((functionMatch = functionRegex.exec(code)) !== null) {
const functionName = functionMatch[1];
const functionCode = extractBlock(code, functionMatch.index);
const description = generateComponentDescription(functionCode, 'function');
mainFunctions.push({ name: functionName, description });
}
// For languages like JavaScript, also look for arrow functions assigned to variables
const arrowFunctionRegex = /const\s+(\w+)\s*=\s*(\([^)]*\)|[^=]*)\s*=>/g;
let arrowMatch;
while ((arrowMatch = arrowFunctionRegex.exec(code)) !== null) {
const functionName = arrowMatch[1];
const functionCode = extractBlock(code, arrowMatch.index);
const description = generateComponentDescription(functionCode, 'function');
mainFunctions.push({ name: functionName, description });
}
return { mainClasses, mainFunctions };
}
/**
* Extracts a code block starting from a given position.
*
* @param code {string} The full source code
* @param startIndex {number} The starting index of the block
* @return {string} The extracted code block
*/
function extractBlock(code: string, startIndex: number): string {
// Find the opening brace after the start index
const openingBraceIndex = code.indexOf('{', startIndex);
if (openingBraceIndex === -1) return '';
// Count braces to find the matching closing brace
let braceCount = 1;
let currentIndex = openingBraceIndex + 1;
while (braceCount > 0 && currentIndex < code.length) {
if (code[currentIndex] === '{') {
braceCount++;
} else if (code[currentIndex] === '}') {
braceCount--;
}
currentIndex++;
}
return code.substring(startIndex, currentIndex);
}
/**
* Generates a detailed description for a code component based on its content.
*
* @param componentCode {string} The code of the component
* @param type {string} The type of component ('class' or 'function')
* @return {string} A description of the component's purpose
*/
function generateComponentDescription(componentCode: string, type: string): string {
// First, look for JSDoc or other documentation comments
let commentRegex: RegExp | null = null;
// Different comment styles for different languages
if (componentCode.includes('"""') || componentCode.includes("'''")) {
// Python docstring
commentRegex = /(?:'''|""")([^]*?)(?:'''|""")/;
} else if (componentCode.includes('/**')) {
// JSDoc style comment
commentRegex = /\/\*\*([^]*?)\*\//;
} else if (componentCode.includes('//')) {
// Single line comments (try to find consecutive ones)
const lines = componentCode.split('\n');
const commentLines: string[] = [];
let inCommentBlock = false;
for (const line of lines) {
const trimmedLine = line.trim();
if (trimmedLine.startsWith('//')) {
commentLines.push(trimmedLine.substring(2).trim());
inCommentBlock = true;
} else if (inCommentBlock && trimmedLine.length === 0) {
// Allow empty lines in comment blocks
continue;
} else {
inCommentBlock = false;
if (commentLines.length > 0) {
break;
}
}
}
if (commentLines.length > 0) {
return commentLines.join(' ');
}
}
// Try to extract comment if regex was set
if (commentRegex) {
const commentMatch = componentCode.match(commentRegex);
if (commentMatch) {
// Clean up the comment
const comment = commentMatch[1]
.replace(/\s*\*\s*/g, ' ') // Remove asterisks from JSDoc
.replace(/\s+/g, ' ') // Normalize whitespace
.replace(/@\w+\s+[^\n]+/g, '') // Remove JSDoc tags
.trim();
if (comment.length > 0) {
return comment;
}
}
}
// If no comment is found, analyze the code to generate a description
// Extract the component name
let componentName = '';
if (type === 'class') {
const classNameMatch = componentCode.match(/class\s+(\w+)/);
if (classNameMatch) {
componentName = classNameMatch[1];
}
} else {
const functionNameMatch = componentCode.match(/function\s+(\w+)|def\s+(\w+)/);
if (functionNameMatch) {
componentName = functionNameMatch[1] || functionNameMatch[2];
}
}
// Convert camelCase or PascalCase to words
if (componentName) {
componentName = componentName
.replace(/([A-Z])/g, ' $1') // Add space before capital letters
.replace(/^./, str => str.toUpperCase()) // Capitalize first letter
.trim();
}
// Analyze code patterns
const patterns: Record<string, RegExp[]> = {
ui: [/render/i, /component/i, /view/i, /display/i, /dom/i, /element/i, /ui/i],
data: [/data/i, /state/i, /store/i, /model/i, /entity/i, /repository/i],
network: [/fetch/i, /http/i, /request/i, /api/i, /url/i, /endpoint/i],
utility: [/util/i, /helper/i, /format/i, /convert/i, /transform/i],
event: [/event/i, /listener/i, /handler/i, /callback/i, /click/i, /change/i],
auth: [/auth/i, /login/i, /permission/i, /role/i, /access/i, /token/i],
file: [/file/i, /read/i, /write/i, /save/i, /load/i, /path/i],
math: [/calc/i, /compute/i, /sum/i, /average/i, /math/i, /formula/i]
};
// Count matches for each category
const matchCounts: Record<string, number> = {};
for (const category in patterns) {
matchCounts[category] = 0;
for (const pattern of patterns[category]) {
if (pattern.test(componentCode)) {
matchCounts[category]++;
}
}
}
// Find the primary purpose based on the most matches
const primaryPurpose = Object.entries(matchCounts)
.sort((a, b) => b[1] - a[1])
.filter(entry => entry[1] > 0)[0]?.[0];
// Generate description based on component type and primary purpose
if (type === 'class') {
switch (primaryPurpose) {
case 'ui':
return `${componentName ? componentName + ' - ' : ''}A UI component that handles rendering and user interaction`;
case 'data':
return `${componentName ? componentName + ' - ' : ''}Manages data and state for the application`;
case 'network':
return `${componentName ? componentName + ' - ' : ''}Provides services or API interactions`;
case 'auth':
return `${componentName ? componentName + ' - ' : ''}Handles authentication and authorization`;
case 'file':
return `${componentName ? componentName + ' - ' : ''}Manages file operations and storage`;
default:
// Check if it's a base/parent class
if (componentCode.includes('extends') || componentCode.includes('implements')) {
return `${componentName ? componentName + ' - ' : ''}A base class that defines core functionality`;
}
return `${componentName ? componentName + ' - ' : ''}Encapsulates related functionality and data`;
}
} else { // function
// Check for parameters and return values
const hasParameters = /\([^)]+\)/.test(componentCode);
const hasReturn = /return/.test(componentCode);
switch (primaryPurpose) {
case 'ui':
return `${componentName ? componentName + ' - ' : ''}${hasReturn ? 'Generates' : 'Renders'} UI elements${hasParameters ? ' based on input parameters' : ''}`;
case 'data':
return `${componentName ? componentName + ' - ' : ''}${hasReturn ? 'Processes and transforms' : 'Manages'} data${hasParameters ? ' from input parameters' : ''}`;
case 'network':
return `${componentName ? componentName + ' - ' : ''}Handles network communication${hasParameters ? ' with specified endpoints' : ''}`;
case 'utility':
return `${componentName ? componentName + ' - ' : ''}Utility function that ${hasReturn ? 'processes input and returns a result' : 'performs operations'}`;
case 'event':
return `${componentName ? componentName + ' - ' : ''}Event handler that responds to user interactions`;
case 'auth':
return `${componentName ? componentName + ' - ' : ''}Manages authentication or authorization processes`;
case 'file':
return `${componentName ? componentName + ' - ' : ''}Handles file system operations`;
case 'math':
return `${componentName ? componentName + ' - ' : ''}Performs mathematical calculations${hasParameters ? ' on input values' : ''}`;
default:
if (hasReturn && hasParameters) {
return `${componentName ? componentName + ' - ' : ''}Processes input parameters and returns a result`;
} else if (hasReturn) {
return `${componentName ? componentName + ' - ' : ''}Computes and returns a value`;
} else if (hasParameters) {
return `${componentName ? componentName + ' - ' : ''}Performs operations based on input parameters`;
} else {
return `${componentName ? componentName + ' - ' : ''}Performs a specific operation or task`;
}
}
}
}
// Main worker handler
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Check if this is a POST request
if (request.method === 'POST') {
// Check for authentication
const authHeader = request.headers.get('Authorization');
const expectedAuth = `Bearer ${env.SHARED_SECRET}`;
if (!authHeader || authHeader !== expectedAuth) {
return new Response('Unauthorized', { status: 401 });
}
// Parse the request body
try {
const body = await request.json() as {
method: string;
params: string[];
};
// Check if this is an MCP request
if (body.method === 'explainCode' && Array.isArray(body.params) && body.params.length >= 2) {
const code = body.params[0];
const language = body.params[1];
// Call the explainCode function
const result = await explainCode(code, language);
// Return the result
return new Response(JSON.stringify({ result }), {
headers: { 'Content-Type': 'application/json' }
});
} else {
return new Response('Invalid method or parameters', { status: 400 });
}
} catch (error: any) {
const errorMessage = error?.message || 'Unknown error';
return new Response(`Error processing request: ${errorMessage}`, { status: 500 });
}
}
// Return a simple HTML page for GET requests
return new Response(`
<!DOCTYPE html>
<html>
<head>
<title>Code Explainer MCP</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
h1 { color: #333; }
pre { background: #f5f5f5; padding: 10px; border-radius: 5px; }
</style>
</head>
<body>
<h1>Code Explainer MCP</h1>
<p>This is a Cloudflare Worker that analyzes and explains code.</p>
<p>To use it, send a POST request with the following JSON body:</p>
<pre>
{
"method": "explainCode",
"params": ["your code here", "programming language"]
}
</pre>
<p>Make sure to include the Authorization header with your shared secret.</p>
</body>
</html>
`, {
headers: { 'Content-Type': 'text/html' }
});
}
};
```