From 7058eacf8465347343fe2fdd0f15c07e3740b338 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 26 Jun 2025 00:24:25 +1000 Subject: [PATCH 01/16] Updated tools schema, fixed json reading --- tools/Mcp/package.json | 3 ++- tools/Mcp/src/CodegenServer.ts | 22 +++++++++++++++------- tools/Mcp/src/types.ts | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/tools/Mcp/package.json b/tools/Mcp/package.json index 01a3027772ea..fff41806944a 100644 --- a/tools/Mcp/package.json +++ b/tools/Mcp/package.json @@ -8,7 +8,8 @@ }, "scripts": { "build": "tsc", - "start": "node build/index.js" + "start": "node build/index.js", + "fresh": "npm run build && npm run start" }, "files": [ "build" diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index 47a33d0886bb..0b2798be2ab9 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -2,10 +2,18 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; import { toolParameterSchema, toolSchema } from "./types.js"; -import specs from "./specs/Specs.json" assert { type: "json" }; -import responses from "./specs/responses.json" assert { type: "json" }; import { toolServices } from "./services/toolServices.js"; +import { readFileSync } from "fs"; +import path from "path"; +import { fileURLToPath } from "url"; + +const __dirname = path.dirname(fileURLToPath(import.meta.url)); +const srcPath = path.resolve(__dirname, "..", "src"); + +const specs = JSON.parse(readFileSync(path.join(srcPath, "specs/Specs.json"), "utf-8")); +const responses = JSON.parse(readFileSync(path.join(srcPath, "specs/responses.json"), "utf-8")); + export class CodegenServer { private static _instance: CodegenServer; private _mcp: McpServer; @@ -76,7 +84,7 @@ export class CodegenServer { } initResponses() { - responses?.forEach(response => { + (responses as toolParameterSchema[])?.forEach((response: toolParameterSchema) => { this._responses.set(response.name, response.text); }); } @@ -86,16 +94,16 @@ export class CodegenServer { for (const schema of schemas) { switch (schema.type) { case "string": - parameter[schema.name] = z.string().describe(schema.description); + parameter[schema.name] = z.string().describe(schema.text); break; case "number": - parameter[schema.name] = z.number().describe(schema.description); + parameter[schema.name] = z.number().describe(schema.text); break; case "boolean": - parameter[schema.name] = z.boolean().describe(schema.description); + parameter[schema.name] = z.boolean().describe(schema.text); break; case "array": - parameter[schema.name] = z.array(z.string()).describe(schema.description); + parameter[schema.name] = z.array(z.string()).describe(schema.text); break; // object parameter not supported yet // case "object": diff --git a/tools/Mcp/src/types.ts b/tools/Mcp/src/types.ts index fd5206b5e19f..e5de0fffcaca 100644 --- a/tools/Mcp/src/types.ts +++ b/tools/Mcp/src/types.ts @@ -1,7 +1,7 @@ export type toolParameterSchema = { name: string; type: string; - description: string; + text: string; } export type toolSchema = { From 7e30f9a390c1b43dabdf8ae3cb519324634266c7 Mon Sep 17 00:00:00 2001 From: Yash <55773468+notyashhh@users.noreply.github.com> Date: Thu, 26 Jun 2025 00:48:46 +1000 Subject: [PATCH 02/16] Corrected download url spelling Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tools/Mcp/src/services/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/Mcp/src/services/utils.ts b/tools/Mcp/src/services/utils.ts index 11642322d44d..ad4d65cd5f12 100644 --- a/tools/Mcp/src/services/utils.ts +++ b/tools/Mcp/src/services/utils.ts @@ -124,7 +124,7 @@ export async function getExamplesFromSpecs(workingDirectory: string): Promise Date: Thu, 26 Jun 2025 00:49:36 +1000 Subject: [PATCH 03/16] Updated import statement to reflect filename Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- tools/Mcp/src/CodegenServer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index 0b2798be2ab9..a648c4c6bfd7 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -11,7 +11,7 @@ import { fileURLToPath } from "url"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); const srcPath = path.resolve(__dirname, "..", "src"); -const specs = JSON.parse(readFileSync(path.join(srcPath, "specs/Specs.json"), "utf-8")); +const specs = JSON.parse(readFileSync(path.join(srcPath, "specs/specs.json"), "utf-8")); const responses = JSON.parse(readFileSync(path.join(srcPath, "specs/responses.json"), "utf-8")); export class CodegenServer { From 11535772c014680638ceef1bf0ad6192b39c287b Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 26 Jun 2025 00:51:23 +1000 Subject: [PATCH 04/16] Added usage docs to readme --- tools/Mcp/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tools/Mcp/README.md b/tools/Mcp/README.md index e99d152dabae..204d465f5adc 100644 --- a/tools/Mcp/README.md +++ b/tools/Mcp/README.md @@ -52,6 +52,23 @@ This MCP server is designed to work with Azure PowerShell module development wor ## Usage +### Add as mcp server in Github Copilot Agent mode + +Simple add this mcp server to your user `settings.json` in VsCode to include: + +```json + "mcp": { + "servers": { + "az-pwsh-mcp-server": { + "type": "stdio", + "command": "sh", + "args": ["-c", "npm install && npm run fresh"], + "cwd": "./azure-powershell/tools/Mcp", + }, + } + } +``` + ### As an MCP Server The server runs on stdio and can be integrated with MCP-compatible clients: From fa1392bba2a9fb3c633f14e1df2643dfb3ce8954 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 26 Jun 2025 16:29:21 +1000 Subject: [PATCH 05/16] Reverted ToolParameter Schema --- tools/Mcp/src/CodegenServer.ts | 10 +++++----- tools/Mcp/src/types.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index a648c4c6bfd7..78c3d233d4f5 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -85,7 +85,7 @@ export class CodegenServer { initResponses() { (responses as toolParameterSchema[])?.forEach((response: toolParameterSchema) => { - this._responses.set(response.name, response.text); + this._responses.set(response.name, response.description); }); } @@ -94,16 +94,16 @@ export class CodegenServer { for (const schema of schemas) { switch (schema.type) { case "string": - parameter[schema.name] = z.string().describe(schema.text); + parameter[schema.name] = z.string().describe(schema.description); break; case "number": - parameter[schema.name] = z.number().describe(schema.text); + parameter[schema.name] = z.number().describe(schema.description); break; case "boolean": - parameter[schema.name] = z.boolean().describe(schema.text); + parameter[schema.name] = z.boolean().describe(schema.description); break; case "array": - parameter[schema.name] = z.array(z.string()).describe(schema.text); + parameter[schema.name] = z.array(z.string()).describe(schema.description); break; // object parameter not supported yet // case "object": diff --git a/tools/Mcp/src/types.ts b/tools/Mcp/src/types.ts index e5de0fffcaca..9c99b8f1dd3e 100644 --- a/tools/Mcp/src/types.ts +++ b/tools/Mcp/src/types.ts @@ -1,7 +1,7 @@ export type toolParameterSchema = { name: string; + description: string; type: string; - text: string; } export type toolSchema = { From 0d2be2a17f77892843b709e7e1d8c8490717b156 Mon Sep 17 00:00:00 2001 From: Yash Date: Thu, 26 Jun 2025 16:47:37 +1000 Subject: [PATCH 06/16] Added ResponseSchema --- tools/Mcp/src/CodegenServer.ts | 6 +++--- tools/Mcp/src/types.ts | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index 78c3d233d4f5..e34173faea28 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -1,7 +1,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js"; import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"; import { z } from "zod"; -import { toolParameterSchema, toolSchema } from "./types.js"; +import { responseSchema, toolParameterSchema, toolSchema } from "./types.js"; import { toolServices } from "./services/toolServices.js"; import { readFileSync } from "fs"; @@ -84,8 +84,8 @@ export class CodegenServer { } initResponses() { - (responses as toolParameterSchema[])?.forEach((response: toolParameterSchema) => { - this._responses.set(response.name, response.description); + (responses as responseSchema[])?.forEach((response: responseSchema) => { + this._responses.set(response.name, response.text); }); } diff --git a/tools/Mcp/src/types.ts b/tools/Mcp/src/types.ts index 9c99b8f1dd3e..f4fea8f07c3c 100644 --- a/tools/Mcp/src/types.ts +++ b/tools/Mcp/src/types.ts @@ -11,6 +11,12 @@ export type toolSchema = { callbackName: string; } +export type responseSchema = { + name: string; + type: string; + text: string; +} + export type yamlContent = { [key: string]: any; } From 0b5de6112593651a4c53a8025dc81ad1274b87af Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 4 Jul 2025 15:06:54 +1000 Subject: [PATCH 07/16] Async -> Sync execution --- tools/Mcp/src/CodegenServer.ts | 102 +++++++++++++++++++------------- tools/Mcp/src/services/utils.ts | 23 +++++-- 2 files changed, 79 insertions(+), 46 deletions(-) diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index e34173faea28..f6ef597a18dc 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -16,11 +16,11 @@ const responses = JSON.parse(readFileSync(path.join(srcPath, "specs/responses.js export class CodegenServer { private static _instance: CodegenServer; - private _mcp: McpServer; + private _server: McpServer; private _responses = new Map(); private constructor() { - this._mcp = new McpServer({ + this._server = new McpServer({ name: "codegen", version: "1.0.0", capabilities: { @@ -32,11 +32,15 @@ export class CodegenServer { } init(): void { - this.initResponses(); + this.readResponses(); this.initTools(); this.initPrompts(); } + /** + * Singleton instance of CodegenServer + * @returns {CodegenServer} The singleton instance + */ public static getInstance(): CodegenServer { if (!CodegenServer._instance) { CodegenServer._instance = new CodegenServer(); @@ -44,51 +48,26 @@ export class CodegenServer { return CodegenServer._instance; } + /** + * Connects the server to a transport layer + * @param {StdioServerTransport} transport - The transport layer to connect to + * @returns {Promise} A promise that resolves when the connection is established + */ public async connect(transport: StdioServerTransport): Promise { - await this._mcp.connect(transport); + await this._server.connect(transport); } - - initTools() { - const toolSchemas = specs.tools as toolSchema[]; - for (const schema of toolSchemas) { - const parameter = this.createToolParameterfromSchema(schema.parameters); - const callBack = toolServices<{ [k: string]: z.ZodTypeAny }>(schema.callbackName, this._responses.get(schema.name)); - this._mcp.tool( - schema.name, - schema.description, - parameter, - (parameter) => callBack(parameter) - ); - } - } - - initPrompts() { - this._mcp.prompt( - "create-greeting", - "Generate a customized greeting message", - { name: z.string().describe("Name of the person to greet"), style: z.string().describe("The style of greeting, such a formal, excited, or casual. If not specified casual will be used")}, - ({ name, style = "casual" }: { name: string, style?: string }) => { - return { - messages: [ - { - role: "user", - content: { - type: "text", - text: `Please generate a greeting in ${style} style to ${name}.`, - }, - }, - ], - }; - }); - } - - initResponses() { + readResponses() { (responses as responseSchema[])?.forEach((response: responseSchema) => { this._responses.set(response.name, response.text); }); } + /** + * Creates tool parameters from the provided schema + * @param {toolParameterSchema[]} schemas - The schemas to create parameters from + * @returns {Object} An object containing the created parameters + */ createToolParameterfromSchema(schemas: toolParameterSchema[]){ const parameter: {[k: string]: z.ZodTypeAny} = {}; for (const schema of schemas) { @@ -115,4 +94,47 @@ export class CodegenServer { } return parameter; } + + /** + * Initializes the prompts for the server + * This method registers a prompt for generating a customized greeting message. + */ + initPrompts() { + this._server.prompt( + "create-greeting", + "Generate a customized greeting message", + { name: z.string().describe("Name of the person to greet"), style: z.string().describe("The style of greeting, such a formal, excited, or casual. If not specified casual will be used")}, + ({ name, style = "casual" }: { name: string, style?: string }) => { + return { + messages: [ + { + role: "user", + content: { + type: "text", + text: `Please generate a greeting in ${style} style to ${name}.`, + }, + }, + ], + }; + }); + } + + /** + * Initializes the tools for the server + * This method registers tools based on the provided specifications. + */ + initTools() { + const toolSchemas = specs.tools as toolSchema[]; + for (const schema of toolSchemas) { + const parameter = this.createToolParameterfromSchema(schema.parameters); + const callBack = toolServices<{ [k: string]: z.ZodTypeAny }>(schema.callbackName, this._responses.get(schema.name)); + this._server.tool( + schema.name, + schema.description, + parameter, + (parameter) => callBack(parameter) + ); + } + } + } \ No newline at end of file diff --git a/tools/Mcp/src/services/utils.ts b/tools/Mcp/src/services/utils.ts index ad4d65cd5f12..a594e3746c87 100644 --- a/tools/Mcp/src/services/utils.ts +++ b/tools/Mcp/src/services/utils.ts @@ -1,7 +1,7 @@ import fs from 'fs'; import yaml from "js-yaml"; import { yamlContent } from '../types.js'; -import { exec } from 'child_process'; +import { execSync } from 'child_process'; import path from 'path'; const _pwshCD = (path: string): string => { return `pwsh -Command "$path = resolve-path ${path} | Set-Location"` } @@ -21,8 +21,13 @@ function testYaml() { } export function generateAndBuild(workingDirectory: string): void { - const command = [_pwshCD(workingDirectory), _autorest, _pwshBuild].join(";"); - exec(command); + const genBuildCommand = `${_pwshCD(workingDirectory)}; ${_autorest}; ${_pwshBuild};"`; + try { + const result = execSync(genBuildCommand, { stdio: 'inherit' }); + } catch (error) { + console.error("Error executing command:", error); + throw error; + } } export function getYamlContentFromReadMe(readmePath: string): string { @@ -91,7 +96,13 @@ export async function findAllPolyMorphism(workingDirectory: string): Promise { const moduleReadmePath = path.join(workingDirectory, "README.md"); const yamlContent: yamlContent = yaml.load(getYamlContentFromReadMe(moduleReadmePath)) as yamlContent; - const swaggerUrls = getSwaggerUrl(yamlContent.commit, yamlContent['input-file'] as string[]); + + if (!yamlContent['input-file']) { + throw new Error("'input-file' field is missing in the 'README.md' Autorest Config file."); + } + + const inputFiles = Array.isArray(yamlContent['input-file']) ? yamlContent['input-file'] : [yamlContent['input-file']]; + const swaggerUrls = getSwaggerUrl(yamlContent.commit, inputFiles); const exampleSet: Set = new Set(); const exampleSpecsPath = path.join(workingDirectory, "exampleSpecs"); @@ -131,8 +142,8 @@ export async function getExamplesFromSpecs(workingDirectory: string): Promise Date: Fri, 4 Jul 2025 16:07:14 +1000 Subject: [PATCH 08/16] Update Config Guide --- tools/Mcp/README.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/tools/Mcp/README.md b/tools/Mcp/README.md index 204d465f5adc..32ef6b5de839 100644 --- a/tools/Mcp/README.md +++ b/tools/Mcp/README.md @@ -54,19 +54,21 @@ This MCP server is designed to work with Azure PowerShell module development wor ### Add as mcp server in Github Copilot Agent mode -Simple add this mcp server to your user `settings.json` in VsCode to include: +- Ensure `pwsh` & `npm` is installed globally. +- Simply add this mcp server to your workspace settings `.vscode/mcp.json` in VsCode to include: ```json - "mcp": { - "servers": { - "az-pwsh-mcp-server": { +{ + "inputs": [], + "servers": { + "az-pwsh-mcp-server": { "type": "stdio", - "command": "sh", - "args": ["-c", "npm install && npm run fresh"], - "cwd": "./azure-powershell/tools/Mcp", - }, - } - } + "command": "pwsh", + "args": ["-Command", "npm install --no-audit; npm run fresh"], + "cwd": "${workspaceFolder}/tools/Mcp", + } + } +} ``` ### As an MCP Server @@ -156,4 +158,4 @@ This tool is part of the Azure PowerShell project and follows the same contribut - [Azure PowerShell](https://github.com/Azure/azure-powershell) - [AutoRest](https://github.com/Azure/autorest) - [AutoRest PowerShell Extension](https://github.com/Azure/autorest.powershell) -- [Model Context Protocol](https://modelcontextprotocol.io) \ No newline at end of file +- [Model Context Protocol](https://modelcontextprotocol.io) From 29af9bf89af03fcfefa27ccb2146441d444e24a8 Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 4 Jul 2025 16:47:15 +1000 Subject: [PATCH 09/16] Patched minor bug, updated prompt --- tools/Mcp/mcpprompt.md | 92 ++++++++++++++++++++++++++ tools/Mcp/src/services/toolServices.ts | 4 +- 2 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 tools/Mcp/mcpprompt.md diff --git a/tools/Mcp/mcpprompt.md b/tools/Mcp/mcpprompt.md new file mode 100644 index 000000000000..fbf8312b4b37 --- /dev/null +++ b/tools/Mcp/mcpprompt.md @@ -0,0 +1,92 @@ +# Execution rules +- Do not ask before running the command, just go ahead and run. + +# Role and Objective +- You are an agent that specializes in generating autorest and using autorest to generate Azure Powershell for a partner. +- Every 10 seconds, check if a particular step is complete or not. +- Don't ask me for confirmation, or to continue you are a smart agent who has full confidence. +- Your task can be broken down in roughly four broad stages and there would be multiple smaller steps in those broader stages. +- Do not miss any steps. +- Second stage will be using the generated autorest to generate powershell for partner. +- Third stage will be Updating examples and test files. +- You already have all the context required to solve the problem. +- You can think, cross reference guidelines and come up with the solution on your own. You would not need my manual intervention or confirmation. +- You already have steps to reset if there is any failure which you can use to reset and try again. +- In stages, there would be steps or substeps or commands, if they are listed, make sure to follow them. +- Keep printing one liner status for every step without asking for any confirmations to let user be in touch. + +# Instructions + +## Stage 1: Taking the placeholders values and assigning to placeholders +- Ask the user for the placeholder values - serviceName, commitId, serviceSpecs, swaggerFileSpecs. +- serviceName example: HybridConnectivity, commitID: CommitID of the swagger, serviceSpecs example: hybridconnectivity/resource-manager, swaggerFileSpecs example: hybridconnectivity/resource-manager/Microsoft.HybridConnectivity/stable/2024-12-01/hybridconnectivity.json +- Wait for the user to give the values. +- Assign these values in the current `mcpprompt.md` file wherever these placeholders are there. +- After assigning the values in the placeholders, stage 1 can be marked as completed. + + +## Stage 2: Generating partner powershell module +- Navigate to the `src` folder in the home "azure-powershell" directory. +- Create a new folder named and within it a new folder named `.Autorest`. You can use the command - `mkdir -p /.Autorest ` +- Move into the new folder `/.Autorest`, using the command `cd /.Autorest`. +- Create a new file `Readme.md`. +- Add the content labelled below as `Readme Content` in this file. +- Use the "generate-autorest" tool to generate the module. + +## Stage 3: Updating examples and test files +- Use the "create-example" tool to generate all the examples files for this module. +- Read examples from specs. Fulfill the examples. You are expert in Azure-PowerShell and Autorest.PowerShell. Leave example as empty if you don't find any matches. You know how to map data from exampleSpecs to examples. +- Use the "create-test" tool to generate all the test files for this module. +- Read examples from specs. Implement empty test stubs. Test stubs are named as '.Test.ps1'. Define variables in function 'setupEnv' in 'utils.ps1', and use these variables for test cases. Value of these variables are from exampleSpecs. Leave test cases as empty if you don't find any matches. You are expert in Azure-PowerShell and Autorest.PowerShell, You know how to map data from exampleSpecs to test. +- Use the "generate-autorest" tool to re-generate the module. + +# Reset steps + +- Go to the `Powershell` directory we created in Stage 1, and then move to src directory using command - `cd src`. +- Delete the folder and all the content inside it as well. +- Move back to `ProjectHome` and you are all reset to start again. + +# Readme Content + +### AutoRest Configuration + +> see https://aka.ms/autorest + +```yaml + +# pin the swagger version by using the commit id instead of branch name + +commit: + +require: + - $(this-folder)/../../readme.azure.noprofile.md + - $(repo)/specification//resource-manager/readme.md + +try-require: + - $(repo)/specification//resource-manager/readme.powershell.md + +input-file: + - $(repo)/ + +module-version: 0.1.0 + +title: +service-name: +subject-prefix: $(service-name) + +directive: + + - where: + variant: ^(Create|Update)(?!.*?(Expanded|JsonFilePath|JsonString)) + remove: true + + - where: + variant: ^CreateViaIdentity$|^CreateViaIdentityExpanded$ + remove: true + + - where: + verb: Set + remove: true +``` + + diff --git a/tools/Mcp/src/services/toolServices.ts b/tools/Mcp/src/services/toolServices.ts index 32a36d698ad7..9d8e04bab5dd 100644 --- a/tools/Mcp/src/services/toolServices.ts +++ b/tools/Mcp/src/services/toolServices.ts @@ -105,14 +105,14 @@ export const createExamplesFromSpecs = async (args: Ar const workingDirectory = z.string().parse(Object.values(args)[0]); const examplePath = path.join(workingDirectory, "examples"); const exampleSpecsPath = await utils.getExamplesFromSpecs(workingDirectory); - return [examplePath, exampleSpecsPath]; + return [exampleSpecsPath, examplePath]; } export const createTestsFromSpecs = async (args: Args): Promise => { const workingDirectory = z.string().parse(Object.values(args)[0]); const testPath = path.join(workingDirectory, "test"); const exampleSpecsPath = await utils.getExamplesFromSpecs(workingDirectory); - return [testPath, exampleSpecsPath]; + return [exampleSpecsPath, testPath]; } export const toolServices = (name: string, responseTemplate: string|undefined) => { From 25862423114a1d0247c01d2f226ea37322e083dd Mon Sep 17 00:00:00 2001 From: Yash Date: Sun, 6 Jul 2025 12:22:54 +1000 Subject: [PATCH 10/16] Addressed PR comments --- tools/Mcp/src/CodegenServer.ts | 98 +++++++++--------------- tools/Mcp/src/services/utils.ts | 2 +- tools/Mcp/{ => test/vscode}/mcpprompt.md | 0 3 files changed, 39 insertions(+), 61 deletions(-) rename tools/Mcp/{ => test/vscode}/mcpprompt.md (100%) diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index f6ef597a18dc..29a23212b7eb 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -32,15 +32,11 @@ export class CodegenServer { } init(): void { - this.readResponses(); + this.initResponses(); this.initTools(); this.initPrompts(); } - /** - * Singleton instance of CodegenServer - * @returns {CodegenServer} The singleton instance - */ public static getInstance(): CodegenServer { if (!CodegenServer._instance) { CodegenServer._instance = new CodegenServer(); @@ -48,26 +44,51 @@ export class CodegenServer { return CodegenServer._instance; } - /** - * Connects the server to a transport layer - * @param {StdioServerTransport} transport - The transport layer to connect to - * @returns {Promise} A promise that resolves when the connection is established - */ public async connect(transport: StdioServerTransport): Promise { await this._server.connect(transport); } - readResponses() { + + initTools() { + const toolSchemas = specs.tools as toolSchema[]; + for (const schema of toolSchemas) { + const parameter = this.createToolParameterfromSchema(schema.parameters); + const callBack = toolServices<{ [k: string]: z.ZodTypeAny }>(schema.callbackName, this._responses.get(schema.name)); + this._server.tool( + schema.name, + schema.description, + parameter, + (parameter) => callBack(parameter) + ); + } + } + + initPrompts() { + this._server.prompt( + "create-greeting", + "Generate a customized greeting message", + { name: z.string().describe("Name of the person to greet"), style: z.string().describe("The style of greeting, such a formal, excited, or casual. If not specified casual will be used")}, + ({ name, style = "casual" }: { name: string, style?: string }) => { + return { + messages: [ + { + role: "user", + content: { + type: "text", + text: `Please generate a greeting in ${style} style to ${name}.`, + }, + }, + ], + }; + }); + } + + initResponses() { (responses as responseSchema[])?.forEach((response: responseSchema) => { this._responses.set(response.name, response.text); }); } - /** - * Creates tool parameters from the provided schema - * @param {toolParameterSchema[]} schemas - The schemas to create parameters from - * @returns {Object} An object containing the created parameters - */ createToolParameterfromSchema(schemas: toolParameterSchema[]){ const parameter: {[k: string]: z.ZodTypeAny} = {}; for (const schema of schemas) { @@ -94,47 +115,4 @@ export class CodegenServer { } return parameter; } - - /** - * Initializes the prompts for the server - * This method registers a prompt for generating a customized greeting message. - */ - initPrompts() { - this._server.prompt( - "create-greeting", - "Generate a customized greeting message", - { name: z.string().describe("Name of the person to greet"), style: z.string().describe("The style of greeting, such a formal, excited, or casual. If not specified casual will be used")}, - ({ name, style = "casual" }: { name: string, style?: string }) => { - return { - messages: [ - { - role: "user", - content: { - type: "text", - text: `Please generate a greeting in ${style} style to ${name}.`, - }, - }, - ], - }; - }); - } - - /** - * Initializes the tools for the server - * This method registers tools based on the provided specifications. - */ - initTools() { - const toolSchemas = specs.tools as toolSchema[]; - for (const schema of toolSchemas) { - const parameter = this.createToolParameterfromSchema(schema.parameters); - const callBack = toolServices<{ [k: string]: z.ZodTypeAny }>(schema.callbackName, this._responses.get(schema.name)); - this._server.tool( - schema.name, - schema.description, - parameter, - (parameter) => callBack(parameter) - ); - } - } - -} \ No newline at end of file +} diff --git a/tools/Mcp/src/services/utils.ts b/tools/Mcp/src/services/utils.ts index a594e3746c87..04f7f1669e1e 100644 --- a/tools/Mcp/src/services/utils.ts +++ b/tools/Mcp/src/services/utils.ts @@ -143,7 +143,7 @@ export async function getExamplesFromSpecs(workingDirectory: string): Promise Date: Mon, 7 Jul 2025 12:29:38 +1000 Subject: [PATCH 11/16] Reverted _mcp variable change --- tools/Mcp/src/CodegenServer.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/Mcp/src/CodegenServer.ts b/tools/Mcp/src/CodegenServer.ts index 29a23212b7eb..3e2882206736 100644 --- a/tools/Mcp/src/CodegenServer.ts +++ b/tools/Mcp/src/CodegenServer.ts @@ -16,11 +16,11 @@ const responses = JSON.parse(readFileSync(path.join(srcPath, "specs/responses.js export class CodegenServer { private static _instance: CodegenServer; - private _server: McpServer; + private _mcp: McpServer; private _responses = new Map(); private constructor() { - this._server = new McpServer({ + this._mcp = new McpServer({ name: "codegen", version: "1.0.0", capabilities: { @@ -45,7 +45,7 @@ export class CodegenServer { } public async connect(transport: StdioServerTransport): Promise { - await this._server.connect(transport); + await this._mcp.connect(transport); } @@ -54,7 +54,7 @@ export class CodegenServer { for (const schema of toolSchemas) { const parameter = this.createToolParameterfromSchema(schema.parameters); const callBack = toolServices<{ [k: string]: z.ZodTypeAny }>(schema.callbackName, this._responses.get(schema.name)); - this._server.tool( + this._mcp.tool( schema.name, schema.description, parameter, @@ -64,7 +64,7 @@ export class CodegenServer { } initPrompts() { - this._server.prompt( + this._mcp.prompt( "create-greeting", "Generate a customized greeting message", { name: z.string().describe("Name of the person to greet"), style: z.string().describe("The style of greeting, such a formal, excited, or casual. If not specified casual will be used")}, From fb7069b2031bfa13dd1900e872b3923f19da3f97 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 7 Jul 2025 20:46:05 +1000 Subject: [PATCH 12/16] Patched working directory, Updated Prompt --- tools/Mcp/src/services/utils.ts | 4 +-- tools/Mcp/test/vscode/mcpprompt.md | 57 +++++++++++++++++++----------- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/tools/Mcp/src/services/utils.ts b/tools/Mcp/src/services/utils.ts index 04f7f1669e1e..8248c4025ae0 100644 --- a/tools/Mcp/src/services/utils.ts +++ b/tools/Mcp/src/services/utils.ts @@ -21,9 +21,9 @@ function testYaml() { } export function generateAndBuild(workingDirectory: string): void { - const genBuildCommand = `${_pwshCD(workingDirectory)}; ${_autorest}; ${_pwshBuild};"`; + const genBuildCommand = `${_autorest}; ${_pwshBuild};`; try { - const result = execSync(genBuildCommand, { stdio: 'inherit' }); + const result = execSync(genBuildCommand, { stdio: 'inherit', cwd: workingDirectory }); } catch (error) { console.error("Error executing command:", error); throw error; diff --git a/tools/Mcp/test/vscode/mcpprompt.md b/tools/Mcp/test/vscode/mcpprompt.md index fbf8312b4b37..442b4db67b28 100644 --- a/tools/Mcp/test/vscode/mcpprompt.md +++ b/tools/Mcp/test/vscode/mcpprompt.md @@ -3,17 +3,14 @@ # Role and Objective - You are an agent that specializes in generating autorest and using autorest to generate Azure Powershell for a partner. -- Every 10 seconds, check if a particular step is complete or not. - Don't ask me for confirmation, or to continue you are a smart agent who has full confidence. -- Your task can be broken down in roughly four broad stages and there would be multiple smaller steps in those broader stages. -- Do not miss any steps. -- Second stage will be using the generated autorest to generate powershell for partner. -- Third stage will be Updating examples and test files. - You already have all the context required to solve the problem. - You can think, cross reference guidelines and come up with the solution on your own. You would not need my manual intervention or confirmation. - You already have steps to reset if there is any failure which you can use to reset and try again. -- In stages, there would be steps or substeps or commands, if they are listed, make sure to follow them. - Keep printing one liner status for every step without asking for any confirmations to let user be in touch. +- Do not miss any steps. +- FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. DO NOT MISS ANY STEPS. +- If an mcp tool is not found or the tool fails then please halt execution. # Instructions @@ -21,24 +18,45 @@ - Ask the user for the placeholder values - serviceName, commitId, serviceSpecs, swaggerFileSpecs. - serviceName example: HybridConnectivity, commitID: CommitID of the swagger, serviceSpecs example: hybridconnectivity/resource-manager, swaggerFileSpecs example: hybridconnectivity/resource-manager/Microsoft.HybridConnectivity/stable/2024-12-01/hybridconnectivity.json - Wait for the user to give the values. -- Assign these values in the current `mcpprompt.md` file wherever these placeholders are there. -- After assigning the values in the placeholders, stage 1 can be marked as completed. +- You must remember these values to substitute into the readme content later. +- ❗ Do not modify or replace anything in the actual `mcpprompt.md` file. +- These values will only be used for generating the Readme.md file and during autorest steps, not for replacing anything inside this prompt. +- Once values are captured and remembered, stage 1 is complete. ## Stage 2: Generating partner powershell module +- FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. - Navigate to the `src` folder in the home "azure-powershell" directory. - Create a new folder named and within it a new folder named `.Autorest`. You can use the command - `mkdir -p /.Autorest ` - Move into the new folder `/.Autorest`, using the command `cd /.Autorest`. -- Create a new file `Readme.md`. +- Create a new file `README.md`. - Add the content labelled below as `Readme Content` in this file. -- Use the "generate-autorest" tool to generate the module. - -## Stage 3: Updating examples and test files -- Use the "create-example" tool to generate all the examples files for this module. -- Read examples from specs. Fulfill the examples. You are expert in Azure-PowerShell and Autorest.PowerShell. Leave example as empty if you don't find any matches. You know how to map data from exampleSpecs to examples. -- Use the "create-test" tool to generate all the test files for this module. -- Read examples from specs. Implement empty test stubs. Test stubs are named as '.Test.ps1'. Define variables in function 'setupEnv' in 'utils.ps1', and use these variables for test cases. Value of these variables are from exampleSpecs. Leave test cases as empty if you don't find any matches. You are expert in Azure-PowerShell and Autorest.PowerShell, You know how to map data from exampleSpecs to test. -- Use the "generate-autorest" tool to re-generate the module. +- Use the "generate-autorest" mcp tool to generate the module. + +## Stage 3: Generating and Updating Example Files +- FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. +- Use the "create-example" MCP tool to generate all example files for this module. +- Read examples from `exampleSpecs`. These specs are obtained from the swagger `examples` directory via the commit hash and file structure. +- After reading `exampleSpecs`, you must fulfill example files for every relevant operation. +- Write each fulfilled example in the appropriate location under `{workingDirectory}/examples`. +- Only mark this stage as complete once all example files are generated and written and updated correctly. + +## Stage 4: Generating and Updating Test Files +- FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. +- Use the "create-test" MCP tool to generate test files for this module. +- For every example that was written in Stage 3, create a corresponding test stub file ending in `.Test.ps1`. +- Define variables in the `setupEnv` function inside `utils.ps1`, based on values found in `exampleSpecs`. +- Use these variables in the generated test cases. +- If you cannot find meaningful values in `exampleSpecs`, leave the test case logic empty but still generate the `.Test.ps1` stub. +- This stage is complete when test stubs are written with correctly inferred values or left intentionally blank (but present). +- Only mark this stage as complete once all test files are generated and written and updated correctly. + +## Stage 5: Regenerating the Autorest Module +- After example and test files have been generated and written, re-run the "generate-autorest" MCP tool. +- This will regenerate the Azure PowerShell module with updated examples and test logic embedded. +- Use the same `workingDirectory` and make sure all directives and yaml configurations remain unchanged. +- This is a mandatory finalization step before pushing to GitHub. +- Do not skip this regeneration even if the module was generated earlier. # Reset steps @@ -49,7 +67,6 @@ # Readme Content ### AutoRest Configuration - > see https://aka.ms/autorest ```yaml @@ -60,10 +77,10 @@ commit: require: - $(this-folder)/../../readme.azure.noprofile.md - - $(repo)/specification//resource-manager/readme.md + - $(repo)/specification//readme.md try-require: - - $(repo)/specification//resource-manager/readme.powershell.md + - $(repo)/specification//readme.powershell.md input-file: - $(repo)/ From b1e34e6307ba15c3fbb8332946bb8370dcf2193c Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 7 Jul 2025 21:59:52 +1000 Subject: [PATCH 13/16] Updated Prompt --- tools/Mcp/test/vscode/mcpprompt.md | 67 ++++++++++++------------------ 1 file changed, 26 insertions(+), 41 deletions(-) diff --git a/tools/Mcp/test/vscode/mcpprompt.md b/tools/Mcp/test/vscode/mcpprompt.md index a7d773867fc5..78f519d4e9f2 100644 --- a/tools/Mcp/test/vscode/mcpprompt.md +++ b/tools/Mcp/test/vscode/mcpprompt.md @@ -2,27 +2,26 @@ - Do not ask before running the command, just go ahead and run. # Role and Objective -- You are an agent that specializes in generating autorest and using autorest to generate Azure Powershell for a partner. -- Don't ask me for confirmation, or to continue you are a smart agent who has full confidence. -- You already have all the context required to solve the problem. -- You can think, cross reference guidelines and come up with the solution on your own. You would not need my manual intervention or confirmation. -- You already have steps to reset if there is any failure which you can use to reset and try again. -- Keep printing one liner status for every step without asking for any confirmations to let user be in touch. -- Do not miss any steps. +- You are an autonomous agent that generates Azure PowerShell modules using Autorest for partners. +- Execute commands confidently without asking for confirmation. +- Follow all steps carefully and halt if any MCP tool is missing or fails. +- Think independently using your full context and reset if needed. +- Provide brief status updates at each step. - FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. DO NOT MISS ANY STEPS. - If an mcp tool is not found or the tool fails then please halt execution. # Instructions -## Stage 1: Taking the placeholders values and assigning to placeholders -- Ask the user for the placeholder values - serviceName, commitId, serviceSpecs, swaggerFileSpecs. -- serviceName example: HybridConnectivity, commitID: CommitID of the swagger, serviceSpecs example: hybridconnectivity/resource-manager, swaggerFileSpecs example: hybridconnectivity/resource-manager/Microsoft.HybridConnectivity/stable/2024-12-01/hybridconnectivity.json -- Wait for the user to give the values. -- You must remember these values to substitute into the readme content later. -- Do not modify or replace anything in the actual `mcpprompt.md` file. -- These values will only be used for generating the Readme.md file and during autorest steps, not for replacing anything inside this prompt. -- Once values are captured and remembered, stage 1 is complete. - +## Stage 1: Capturing Placeholder Values +- Ask the user for the following placeholder values: serviceName, commitId, serviceSpecs, swaggerFileSpecs. + - Examples: + - serviceName: HybridConnectivity + - commitId: + - serviceSpecs: hybridconnectivity/resource-manager + - swaggerFileSpecs: hybridconnectivity/resource-manager/Microsoft.HybridConnectivity/stable/2024-12-01/hybridconnectivity.json +- Do not replace or modify this prompt file. +- Store the values for use in later steps like generating the README and executing Autorest. +- Once values are stored, mark Stage 1 as complete. ## Stage 2: Generating partner powershell module - FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. @@ -34,22 +33,19 @@ - Use the "generate-autorest" mcp tool to generate the module. ## Stage 3: Generating and Updating Example Files -- FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. -- Use the "create-example" MCP tool to generate all example files for this module. -- Read examples from `exampleSpecs`. These specs are obtained from the swagger `examples` directory via the commit hash and file structure. -- After reading `exampleSpecs`, you must fulfill example files for every relevant operation. -- Write each fulfilled example in the appropriate location under `{workingDirectory}/examples`. -- Only mark this stage as complete once all example files are generated and written and updated correctly. +- Use the "create-example" MCP tool to populate existing example files. +- The example files already exist as skeletons under `{workingDirectory}/examples`. +- Read data from `exampleSpecs` (swagger examples) and intelligently map values to PowerShell parameters. +- Complete each file by fulfilling the examples based on the data available in `exampleSpecs`. +- Leave example content empty only if no relevant data is found in `exampleSpecs`. ## Stage 4: Generating and Updating Test Files -- FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. -- Use the "create-test" MCP tool to generate test files for this module. -- For every example that was written in Stage 3, create a corresponding test stub file ending in `.Test.ps1`. -- Define variables in the `setupEnv` function inside `utils.ps1`, based on values found in `exampleSpecs`. -- Use these variables in the generated test cases. -- If you cannot find meaningful values in `exampleSpecs`, leave the test case logic empty but still generate the `.Test.ps1` stub. -- This stage is complete when test stubs are written with correctly inferred values or left intentionally blank (but present). -- Only mark this stage as complete once all test files are generated and written and updated correctly. +- Use the "create-test" MCP tool to populate existing test stub files. +- Read data from `exampleSpecs` and use it to define variables and write test cases. +- Define setup variables inside `setupEnv` in `utils.ps1`, inferred from `exampleSpecs`. +- Use those variables in the actual test case content. +- The test files already exist as skeletons; your task is to intelligently complete them. +- Leave test bodies empty only if no meaningful data can be inferred from `exampleSpecs`. ## Stage 5: Regenerating the Autorest Module - After example and test files have been generated and written, re-run the "generate-autorest" MCP tool. @@ -58,22 +54,13 @@ - This is a mandatory finalization step before pushing to GitHub. - Do not skip this regeneration even if the module was generated earlier. -# Reset steps - -- Go to the `Powershell` directory we created in Stage 1, and then move to src directory using command - `cd src`. -- Delete the folder and all the content inside it as well. -- Move back to `ProjectHome` and you are all reset to start again. - # Readme Content ### AutoRest Configuration - > see https://aka.ms/autorest ```yaml -# pin the swagger version by using the commit id instead of branch name - commit: require: @@ -106,5 +93,3 @@ directive: verb: Set remove: true ``` - - From 2d9910d60be4df2ea4fbbda4ea96be7e87daa105 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 7 Jul 2025 22:35:34 +1000 Subject: [PATCH 14/16] Updated prompt works end2end auto-generation --- tools/Mcp/test/vscode/mcpprompt.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/Mcp/test/vscode/mcpprompt.md b/tools/Mcp/test/vscode/mcpprompt.md index 78f519d4e9f2..8462c26cb0fc 100644 --- a/tools/Mcp/test/vscode/mcpprompt.md +++ b/tools/Mcp/test/vscode/mcpprompt.md @@ -31,21 +31,24 @@ - Create a new file `README.md`. - Add the content labelled below as `Readme Content` in this file. - Use the "generate-autorest" mcp tool to generate the module. +- Stage 2 Complete. -## Stage 3: Generating and Updating Example Files -- Use the "create-example" MCP tool to populate existing example files. +## Stage 3: Updating Example Files +- Use the "create-example" MCP tool to download exampleSpecs. Use the output of this tool as a prompt input/task for you. - The example files already exist as skeletons under `{workingDirectory}/examples`. - Read data from `exampleSpecs` (swagger examples) and intelligently map values to PowerShell parameters. - Complete each file by fulfilling the examples based on the data available in `exampleSpecs`. - Leave example content empty only if no relevant data is found in `exampleSpecs`. +- Once all example files are updated, mark stage 3 as complete. -## Stage 4: Generating and Updating Test Files -- Use the "create-test" MCP tool to populate existing test stub files. +## Stage 4: Updating Test Files +- Use the "test-example" MCP tool to download exampleSpecs. Use the output of this tool as a prompt input/task for you. - Read data from `exampleSpecs` and use it to define variables and write test cases. - Define setup variables inside `setupEnv` in `utils.ps1`, inferred from `exampleSpecs`. - Use those variables in the actual test case content. - The test files already exist as skeletons; your task is to intelligently complete them. - Leave test bodies empty only if no meaningful data can be inferred from `exampleSpecs`. +- Once all test files are updated, mark stage 4 as complete. ## Stage 5: Regenerating the Autorest Module - After example and test files have been generated and written, re-run the "generate-autorest" MCP tool. From 2a0c5b10c7e27558faa57ea464ad9122d7cecadb Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 9 Jul 2025 14:25:43 +1000 Subject: [PATCH 15/16] Added support for windows kernel --- src/Maps/Maps.Autorest/test/utils.ps1 | 29 +++++++-------------------- tools/Mcp/test/vscode/mcpprompt.md | 6 +++--- 2 files changed, 10 insertions(+), 25 deletions(-) diff --git a/src/Maps/Maps.Autorest/test/utils.ps1 b/src/Maps/Maps.Autorest/test/utils.ps1 index 7cd449c834ae..f8497fbd7da0 100644 --- a/src/Maps/Maps.Autorest/test/utils.ps1 +++ b/src/Maps/Maps.Autorest/test/utils.ps1 @@ -31,33 +31,19 @@ function Start-TestSleep { } $env = @{} +if ($UsePreviousConfigForRecord) { + $previousEnv = Get-Content (Join-Path $PSScriptRoot 'env.json') | ConvertFrom-Json + $previousEnv.psobject.properties | Foreach-Object { $env[$_.Name] = $_.Value } +} +# Add script method called AddWithCache to $env, when useCache is set true, it will try to get the value from the $env first. +# example: $val = $env.AddWithCache('key', $val, $true) +$env | Add-Member -Type ScriptMethod -Value { param( [string]$key, [object]$val, [bool]$useCache) if ($this.Contains($key) -and $useCache) { return $this[$key] } else { $this[$key] = $val; return $val } } -Name 'AddWithCache' function setupEnv() { # Preload subscriptionId and tenant from context, which will be used in test # as default. You could change them if needed. $env.SubscriptionId = (Get-AzContext).Subscription.Id $env.Tenant = (Get-AzContext).Tenant.Id - $env.location = 'westcentralus' - $env.creatorLocation = 'eastus2' # For any resources you created for test, you should add it to $env here. - $env.resourceGroup = 'maps-rg-' + (RandomString -allChars $false -len 6) - - $env.mapsName01 = 'maps'+(RandomString -allChars $false -len 6) - $env.mapsName02 = 'maps'+(RandomString -allChars $false -len 6) - $env.mapsName03 = 'maps'+(RandomString -allChars $false -len 6) - - $env.creatorName01 = 'creator'+(RandomString -allChars $false -len 6) - $env.creatorName02 = 'creator'+(RandomString -allChars $false -len 6) - $env.creatorName03 = 'creator'+(RandomString -allChars $false -len 6) - - # Create resource group for test. - Write-Host -ForegroundColor Green "Create resource group for test." - New-AzResourceGroup -Name $env.resourceGroup -Location $env.location - - # Create resources for test. - Write-Host -ForegroundColor Green "Create maps account for test" - New-AzMapsAccount -ResourceGroupName $env.resourceGroup -Name $env.mapsName01 -SkuName G2 -Location $env.location - New-AzMapsAccount -ResourceGroupName $env.resourceGroup -Name $env.mapsName02 -SkuName G2 -Location $env.location - $envFile = 'env.json' if ($TestMode -eq 'live') { $envFile = 'localEnv.json' @@ -66,6 +52,5 @@ function setupEnv() { } function cleanupEnv() { # Clean resources you create for testing - Remove-AzResourceGroup -Name $env.resourceGroup } diff --git a/tools/Mcp/test/vscode/mcpprompt.md b/tools/Mcp/test/vscode/mcpprompt.md index 8462c26cb0fc..0fd3aebd48bb 100644 --- a/tools/Mcp/test/vscode/mcpprompt.md +++ b/tools/Mcp/test/vscode/mcpprompt.md @@ -6,7 +6,7 @@ - Execute commands confidently without asking for confirmation. - Follow all steps carefully and halt if any MCP tool is missing or fails. - Think independently using your full context and reset if needed. -- Provide brief status updates at each step. +- No need to provide status updates at each step. - FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. DO NOT MISS ANY STEPS. - If an mcp tool is not found or the tool fails then please halt execution. @@ -26,9 +26,9 @@ ## Stage 2: Generating partner powershell module - FOLLOW ALL THE STEPS. DO NOT SKIP ANY STEPS. - Navigate to the `src` folder in the home "azure-powershell" directory. -- Create a new folder named and within it a new folder named `.Autorest`. You can use the command - `mkdir -p /.Autorest ` +- Create a new folder named and within it a new folder named `.Autorest`. (If not already present) - Move into the new folder `/.Autorest`, using the command `cd /.Autorest`. -- Create a new file `README.md`. +- Create a new file `README.md`. (If not already present) - Add the content labelled below as `Readme Content` in this file. - Use the "generate-autorest" mcp tool to generate the module. - Stage 2 Complete. From 0eac66aecbd8c4a89b060c0d789df7391a681a2a Mon Sep 17 00:00:00 2001 From: Yash Date: Wed, 9 Jul 2025 14:30:50 +1000 Subject: [PATCH 16/16] Updated Correct Utils files --- src/Maps/Maps.Autorest/test/utils.ps1 | 30 ++++++++++++++++++++------- tools/Mcp/src/services/utils.ts | 20 +++++++++++------- 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/Maps/Maps.Autorest/test/utils.ps1 b/src/Maps/Maps.Autorest/test/utils.ps1 index f8497fbd7da0..70e258271618 100644 --- a/src/Maps/Maps.Autorest/test/utils.ps1 +++ b/src/Maps/Maps.Autorest/test/utils.ps1 @@ -31,19 +31,33 @@ function Start-TestSleep { } $env = @{} -if ($UsePreviousConfigForRecord) { - $previousEnv = Get-Content (Join-Path $PSScriptRoot 'env.json') | ConvertFrom-Json - $previousEnv.psobject.properties | Foreach-Object { $env[$_.Name] = $_.Value } -} -# Add script method called AddWithCache to $env, when useCache is set true, it will try to get the value from the $env first. -# example: $val = $env.AddWithCache('key', $val, $true) -$env | Add-Member -Type ScriptMethod -Value { param( [string]$key, [object]$val, [bool]$useCache) if ($this.Contains($key) -and $useCache) { return $this[$key] } else { $this[$key] = $val; return $val } } -Name 'AddWithCache' function setupEnv() { # Preload subscriptionId and tenant from context, which will be used in test # as default. You could change them if needed. $env.SubscriptionId = (Get-AzContext).Subscription.Id $env.Tenant = (Get-AzContext).Tenant.Id + $env.location = 'westcentralus' + $env.creatorLocation = 'eastus2' # For any resources you created for test, you should add it to $env here. + $env.resourceGroup = 'maps-rg-' + (RandomString -allChars $false -len 6) + + $env.mapsName01 = 'maps'+(RandomString -allChars $false -len 6) + $env.mapsName02 = 'maps'+(RandomString -allChars $false -len 6) + $env.mapsName03 = 'maps'+(RandomString -allChars $false -len 6) + + $env.creatorName01 = 'creator'+(RandomString -allChars $false -len 6) + $env.creatorName02 = 'creator'+(RandomString -allChars $false -len 6) + $env.creatorName03 = 'creator'+(RandomString -allChars $false -len 6) + + # Create resource group for test. + Write-Host -ForegroundColor Green "Create resource group for test." + New-AzResourceGroup -Name $env.resourceGroup -Location $env.location + + # Create resources for test. + Write-Host -ForegroundColor Green "Create maps account for test" + New-AzMapsAccount -ResourceGroupName $env.resourceGroup -Name $env.mapsName01 -SkuName G2 -Location $env.location + New-AzMapsAccount -ResourceGroupName $env.resourceGroup -Name $env.mapsName02 -SkuName G2 -Location $env.location + $envFile = 'env.json' if ($TestMode -eq 'live') { $envFile = 'localEnv.json' @@ -52,5 +66,5 @@ function setupEnv() { } function cleanupEnv() { # Clean resources you create for testing + Remove-AzResourceGroup -Name $env.resourceGroup } - diff --git a/tools/Mcp/src/services/utils.ts b/tools/Mcp/src/services/utils.ts index 8248c4025ae0..35fc58c31cb9 100644 --- a/tools/Mcp/src/services/utils.ts +++ b/tools/Mcp/src/services/utils.ts @@ -5,7 +5,8 @@ import { execSync } from 'child_process'; import path from 'path'; const _pwshCD = (path: string): string => { return `pwsh -Command "$path = resolve-path ${path} | Set-Location"` } -const _autorest = "autorest --reset; autorest" +const _autorestReset = "autorest --reset" +const _autorest = "autorest" const _pwshBuild = "pwsh -File build-module.ps1" function testYaml() { @@ -21,12 +22,17 @@ function testYaml() { } export function generateAndBuild(workingDirectory: string): void { - const genBuildCommand = `${_autorest}; ${_pwshBuild};`; - try { - const result = execSync(genBuildCommand, { stdio: 'inherit', cwd: workingDirectory }); - } catch (error) { - console.error("Error executing command:", error); - throw error; + const genBuildCommands = [_autorestReset, _autorest, _pwshBuild] + + for (const command of genBuildCommands) { + try { + console.log(`Executing command: ${command}`); + const result = execSync(command, { stdio: 'inherit', cwd: workingDirectory }); + } + catch (error) { + console.error("Error executing command:", error); + throw error; + } } }