Skip to content

Commit ffefc43

Browse files
authored
Update azsdk readme (#11284)
* Update azsdk readme * Add design guidelines * Add note about mcp:cli 1:1 tool mapping exceptions
1 parent 0ca82fb commit ffefc43

File tree

3 files changed

+132
-88
lines changed

3 files changed

+132
-88
lines changed

tools/azsdk-cli/Azure.Sdk.Tools.Cli/Tools/HelloWorldTool/HelloWorldTool.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
namespace Azure.Sdk.Tools.Cli.Tools.HelloWorldTool
1212
{
1313
#if DEBUG
14-
[McpServerToolType, Description("Echoes the message back to the client.")]
14+
[McpServerToolType, Description("Echoes the message back to the client")]
1515
public class HelloWorldTool(ILogger<HelloWorldTool> logger, IOutputService output) : MCPTool
1616
{
1717
private Argument<string> _inputArg = new Argument<string>(

tools/azsdk-cli/CONTRIBUTING.md

Lines changed: 0 additions & 50 deletions
This file was deleted.

tools/azsdk-cli/README.md

Lines changed: 131 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,150 @@
1-
# The engsys `everything` server
1+
# Azure SDK CLI and MCP server
22

3-
This tool will serve as the primary integration point for all of the `azure-sdk` provided MCP tools. This tool will be built and published out of the `azure-sdk-tools` repo, but consumed primarily through the `.vscode/mcp.json` within each `Azure-sdk-for-X` language repo. Tool installation will be carried out by the eng/common scripts present at `eng/common/mcp/azure-sdk-mcp.ps`.
3+
This project is the primary integration point for all `azure-sdk` provided [MCP](https://modelcontextprotocol.io/introduction) tools as well as a convenient CLI app for azure sdk developers. It is built and published out of the `azure-sdk-tools` repo but consumed primarily through the `.vscode/mcp.json` file within each `Azure-sdk-for-<lang>` language repository. Server installation is carried out by the eng/common scripts present at `eng/common/mcp/azure-sdk-mcp.ps1`.
44

5-
## Integration
5+
* [Getting Started](#getting-started)
6+
* [Prerequisites](#prerequisites)
7+
* [Setup](#setup)
8+
* [Build](#build)
9+
* [Run](#run)
10+
* [Test](#test)
11+
* [Project Structure and Information](#project-structure-and-information)
12+
* [Directory Structure](#directory-structure)
13+
* [Pipelines](#pipelines)
14+
* [Adding a New Tool](#adding-a-new-tool)
615

7-
This `everything` or `hub` server starts up and _should_ be able to pass requests for the requested tool. How the server actually runs these classes is very important. Especially when it comes to versioning etc.
16+
## Getting Started
817

9-
These are different proposals for how we can organize this. Examples will be linked within this same folder until we settle on one.
18+
### Prerequisites
1019

11-
### Specific classes within a server
20+
- [.NET 8.0 SDK or later](https://dotnet.microsoft.com/download)
1221

13-
Users will add classes to a specific folder in the hub server's code. These classes will have to meet an interface, but will be free to implement however they want other than that.
22+
### Setup
1423

15-
|Pro/Con|Description|
16-
|---|---|
17-
||Very easy for users to add new functionalities.|
18-
|🟥|Version selection will be gated at the server.|
19-
|🟥|Aside from disabling specific `tools` and changing installed version of the `hub` server, users won't be able to customize their server installation|
24+
1. Clone the repository:
25+
```sh
26+
git clone https://github.com/Azure/azure-sdk-tools.git
27+
cd azure-sdk-tools/tools/azsdk-cli
28+
```
2029

21-
### Individual MCP servers that are **referenced** from `hub`
30+
2. Restore dependencies:
31+
```sh
32+
dotnet restore
33+
```
2234

23-
Everything server csproj:
35+
### Build
2436

25-
```xml
26-
<ItemGroup>
27-
<PackageReference Include="Azure.SDK.Tools.MCP.ToolName1" Version="1.0.0" />
28-
<PackageReference Include="Azure.SDK.Tools.MCP.ToolName2" Version="1.0.0" />
29-
<PackageReference Include="Azure.SDK.Tools.MCP.ToolName3" Version="1.0.0" />
37+
To build the project:
38+
39+
```sh
40+
dotnet build
41+
```
42+
43+
### Run
44+
45+
To run the CLI locally:
46+
47+
```sh
48+
dotnet run --project Azure.Sdk.Tools.Cli -- --help
3049
```
3150

32-
My vision here is that these individual tools should be:
33-
- implemented as standalone servers
34-
- when DI-ed into our `hub` server, provide a `route` that can be provided by the hub server
51+
### Test
52+
53+
To run the tests:
54+
55+
```sh
56+
dotnet test
57+
```
58+
59+
## Project Structure and Information
60+
61+
This project is both a [System.CommandLine](https://learn.microsoft.com/en-us/dotnet/standard/commandline/) app and an MCP server using the [MCP C# SDK](https://github.com/modelcontextprotocol/csharp-sdk).
3562

36-
This way, users can add local `mcp`
63+
### Directory Structure
3764

38-
|Pro/Con|Description|
39-
|---|---|
40-
||Tools will work standalone for easy development and testing.|
41-
||Much more granular control over what versions of which tools are present in the hub.|
42-
|🟥|Users will have to match a server convention at the very least, and implement an interface that makes their actual workload pluggable into the `hub`.|
43-
|🟥|EngSys will need to add good integration testing of the contract, so that local development -> deployment in `everything server` will never surprise them.|
65+
- *Azure.Sdk.Tools.Cli* - Core project for cli/mcp logic
66+
- *Commands* - Shared classes for CLI commands
67+
- *Configuration* - Constants and other classes
68+
- *Helpers* - Helper logic for parsing data
69+
- *Models* - Shared models, response classes and schemas
70+
- *Services* - Helper classes for working with upstream services, e.g. azure, devops, github
71+
- *Tools* - CLI commands and MCP tool implementations
72+
- *Azure.Sdk.Tools.Cli.Tests* - Test project
73+
- *Azure.Sdk.Tools.Cli.Contract* - Common classes/interfaces
74+
- *Azure.Sdk.Tools.Cli.Analyzer* - Compilation addons to enforce conventions
75+
- Enforce all tools handled by try/catch
76+
- Enforce tool inclusion in service registration for dependency injector
4477

45-
## Additional features
78+
### Pipelines
4679

47-
Concept of `chaining` of various MCP servers. Can this hub support taking the output of one spoke and shoving it to another? We probably should right?
80+
Public CI - https://dev.azure.com/azure-sdk/public/_build?definitionId=7677
4881

82+
Release - https://dev.azure.com/azure-sdk/internal/_build?definitionId=7684
4983

50-
## Some random DOs and DON'Ts of this server
84+
## Design Guidelines
85+
86+
- Think of the server primarily as a first class CLI app
87+
- Add attributes to enable MCP hooks, but MCP server functionality is a pluggable feature, not foundational to the architecture
88+
- Rapid ad-hoc testing is easier via CLI than MCP, and any tools we build can be consumed by other software/scripts outside of MCP
89+
- For example, the engsys/azsdk cli app is built around System.CommandLine along with some dependency injection and ASP.net glue + attributes to get it working with the MCP C# sdk
90+
- Return structured data from all tools/commands. Define response classes that can `ToString()` or `ToJson()` for different output modes (and handle failure flows)
91+
- Write debug logging to stderr and/or a file in MCP mode. This avoids the misleading "FAILURE TO PARSE MESSAGE" type errors in the MCP client logs
92+
- Support both stdio and http mode for MCP to enable easy debugging with tools like mcp inspector
93+
- Where possible, avoid dependencies/pre-requisites requiring manual setup, prefer being able to set them up within the app (e.g. az login, gh login, etc.)
94+
95+
## Adding a New Tool
96+
97+
Tool classes are the core of the azure sdk app and implement CLI commands or MCP server tools. To add a new tool start with the following:
98+
99+
- Determine the right directory and tool class name under `Azure.Sdk.Tools.Cli/Tools`
100+
- Reference or copy from the [hello world tool](Azure.Sdk.Tools.Cli/Tools/HelloWorldTool/HelloWorldTool.cs) for an example.
101+
- See [Tools/README.md](./Azure.Sdk.Tools.Cli/Tools/README.md) for more details
102+
103+
Each tool class should implement a `GetCommand()` method and a `HandleCommand(...)` method. These allow the tools to be called from CLI mode.
104+
Some exceptions may apply on a case by case basis for tool classes where we implement MCP mode but not CLI mode and vice versa.
105+
106+
```csharp
107+
public override Command GetCommand()
108+
{
109+
Command command = new("example", "An example CLI command");
110+
command.SetHandler(async ctx => { await HandleCommand(ctx, ctx.GetCancellationToken()); });
111+
return command;
112+
}
113+
114+
public override async Task HandleCommand(InvocationContext ctx, CancellationToken ct)
115+
{
116+
var result = await SomeMethod();
117+
ctx.ExitCode = ExitCode;
118+
output.Output(result);
119+
}
120+
```
121+
122+
Additionally, the tool class and any methods that will be included in the MCP server tools list must have the MCP attributes:
123+
124+
```csharp
125+
[McpServerToolType, Description("Example tool")]
126+
public class ExampleTool(ILogger<ExampleTool> logger, IOutputService output) : MCPTool
127+
{
128+
[McpServerTool(Name = "example-1"), Description("Example tool call 1")]
129+
public DefaultCommandResponse Success(string message)
130+
{
131+
try
132+
{
133+
return new()
134+
{
135+
Message = "success"
136+
}
137+
}
138+
catch (Exception ex)
139+
{
140+
SetFailure(1);
141+
return new()
142+
{
143+
ResponseError = $"failure: {ex.Message}"
144+
}
145+
}
146+
}
147+
}
148+
```
51149
52-
- [x] DO build with the idea that authentication WILL be coming. Right now the sole protection we have is that these tools will be running in context of the "current user." This means access to `DefaultAzureCredential` should be enough to allow it to function. Users will be adding other external servers to their `mcp.json` at their own risk.
53-
- What does this actually look like in practice?
54-
- [x] DO Provide `--tools` startup parameter:
55-
- Provide `--tools <name>,<name>,<name>` to _enable_ specific functionalities of the `hub` server?
56-
- Provide `--tools-exclude <name>,<name>,<name>` to _disable_ specific functionalities of the `hub` server?
150+
**Rather than bubbling up exceptions, all `McpServerTool` methods must handle failures and format them into its response object. This allows tools to be interoperable between CLI and MCP mode.**

0 commit comments

Comments
 (0)