Skip to content

Commit d522e97

Browse files
author
Hannia Valera
committed
Add onboarding MCP server and setup guide for new contributors
1 parent a12ba8d commit d522e97

9 files changed

Lines changed: 298 additions & 0 deletions

File tree

.vscode/mcp.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{
2+
"servers": {
3+
"cmake-tools-onboarding": {
4+
"type": "stdio",
5+
"command": "node",
6+
"args": ["${workspaceFolder}/tools/onboarding-mcp/dist/index.js"]
7+
}
8+
}
9+
}

tools/onboarding-mcp/README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
# CMake Tools Onboarding MCP Server
2+
3+
A [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that helps new contributors onboard to the [vscode-cmake-tools](https://github.com/microsoft/vscode-cmake-tools) extension. It provides Copilot agent mode with structured, repo-specific knowledge about setup, code structure, and PR requirements.
4+
5+
## Install and build
6+
7+
```bash
8+
cd tools/onboarding-mcp
9+
npm install # or: yarn install
10+
npm run build # or: yarn build
11+
```
12+
13+
## Wire it up in VS Code
14+
15+
Add the following to your **`.vscode/mcp.json`** at the workspace root:
16+
17+
```json
18+
{
19+
"servers": {
20+
"cmake-tools-onboarding": {
21+
"type": "stdio",
22+
"command": "node",
23+
"args": ["${workspaceFolder}/tools/onboarding-mcp/dist/index.js"]
24+
}
25+
}
26+
}
27+
```
28+
29+
Once configured, the MCP server is available to Copilot agent mode (and any other MCP client) in VS Code.
30+
31+
## Development
32+
33+
```bash
34+
# Run the server in dev mode (uses tsx, no build step needed):
35+
npm run dev
36+
37+
# Build for production:
38+
npm run build
39+
40+
# Run the production build:
41+
npm start
42+
```
43+
44+
## Available tools
45+
46+
| Tool | Description |
47+
| --- | --- |
48+
| **`get_setup_guide`** | Returns an ordered list of setup steps for new contributors to build and run the extension locally. No inputs required. Each step includes a number, title, optional shell command, and optional notes. |
49+
| **`check_pr_readiness`** | Given a free-text description of changes (`{ "changes": "..." }`), returns a checklist of PR requirements from CONTRIBUTING.md. Each item includes the rule, a status (`"pass"`, `"warn"`, or `"manual_check_required"`), and a helpful hint. Items are flagged as `"warn"` when the description suggests a potential issue (e.g. mentioning `package.json` changes). |

tools/onboarding-mcp/package.json

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{
2+
"name": "cmake-tools-onboarding-mcp",
3+
"version": "0.1.0",
4+
"private": true,
5+
"description": "MCP server to help new contributors onboard to microsoft/vscode-cmake-tools",
6+
"type": "module",
7+
"scripts": {
8+
"build": "tsc",
9+
"dev": "tsx src/index.ts",
10+
"start": "node dist/index.js"
11+
},
12+
"dependencies": {
13+
"@modelcontextprotocol/sdk": "^1.27.1",
14+
"zod": "^3.25.0"
15+
},
16+
"devDependencies": {
17+
"@types/node": "^22.0.0",
18+
"tsx": "^4.19.0",
19+
"typescript": "^5.7.0"
20+
}
21+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
export interface PrRule {
2+
id: string;
3+
rule: string;
4+
hint: string;
5+
/** If the user's change description contains any of these keywords, flag the rule as "warn". */
6+
warnKeywords?: string[];
7+
}
8+
9+
export const prRules: PrRule[] = [
10+
{
11+
id: "changelog",
12+
rule: "Updated CHANGELOG.md as part of the PR",
13+
hint: "Add an entry under the current version in CHANGELOG.md describing your user-visible change. Follow the existing tense and category style (Features / Improvements / Bug Fixes)."
14+
},
15+
{
16+
id: "naming-convention",
17+
rule: "New variables use lowerCamelCase, not snake_case",
18+
hint: "snake_case was used historically but is being phased out. All new variables must use lowerCamelCase."
19+
},
20+
{
21+
id: "yarn-lock-unchanged",
22+
rule: "yarn.lock was NOT modified and NOT committed",
23+
hint: "If you deleted .npmrc for local dev, yarn.lock may have changed. Revert it before committing: git checkout yarn.lock"
24+
},
25+
{
26+
id: "npmrc-unchanged",
27+
rule: ".npmrc was NOT committed",
28+
hint: "The .npmrc file points to an Azure Artifacts feed and must not be modified or deleted in your PR."
29+
},
30+
{
31+
id: "lint-passes",
32+
rule: "yarn run lint was run and passes",
33+
hint: "Run 'yarn run lint' locally and fix all warnings and errors before submitting your PR."
34+
},
35+
{
36+
id: "coding-guidelines",
37+
rule: "TypeScript coding guidelines followed",
38+
hint: "Follow the TypeScript coding guidelines: https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines. Code is formatted using the default TypeScript formatter in VS Code with 4-space indentation."
39+
},
40+
{
41+
id: "dependency-changes",
42+
rule: "If package.json dependencies were added or changed, the team was pinged in the PR",
43+
hint: "Dependency changes require intervention from the CMake Tools team because the repo uses an Azure Artifacts feed. Mention @microsoft/vscode-cmake-tools in the PR.",
44+
warnKeywords: ["package.json", "dependency", "dependencies", "npm install", "yarn add", "added a package", "updated a package", "new dependency"]
45+
}
46+
];
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
export interface SetupStep {
2+
step: number;
3+
title: string;
4+
command?: string;
5+
notes?: string;
6+
}
7+
8+
export const setupSteps: SetupStep[] = [
9+
{
10+
step: 1,
11+
title: "Install Node.js",
12+
notes: "Download and install from https://nodejs.org/en/. The LTS version is recommended."
13+
},
14+
{
15+
step: 2,
16+
title: "Install yarn globally",
17+
command: "npm install -g yarn",
18+
notes: "yarn is used to compile the code and manage dependencies in this repo."
19+
},
20+
{
21+
step: 3,
22+
title: "Clone the repo and open it in VS Code",
23+
command: "git clone https://github.com/microsoft/vscode-cmake-tools.git && code vscode-cmake-tools",
24+
notes: "You can also open the cloned folder from VS Code's File > Open Folder menu."
25+
},
26+
{
27+
step: 4,
28+
title: "Delete .npmrc for local development",
29+
command: "rm .npmrc",
30+
notes: "The repo points the package manager to a public Azure Artifacts feed via .npmrc. Deleting it lets you use the default npm registry for local dev. Do NOT commit this deletion."
31+
},
32+
{
33+
step: 5,
34+
title: "Install dependencies",
35+
command: "yarn install",
36+
notes: "Installs all required packages. If you skipped step 4, this may fail due to the Azure Artifacts feed requiring authentication."
37+
},
38+
{
39+
step: 6,
40+
title: "Build and run the extension",
41+
command: "Press F5 in VS Code",
42+
notes: "This compiles the extension and launches it in a new Extension Development Host window. You can set breakpoints in the TypeScript source before pressing F5."
43+
},
44+
{
45+
step: 7,
46+
title: "Lint the code",
47+
command: "yarn run lint",
48+
notes: "Run this before submitting a PR. Warnings from eslint appear in the Errors and Warnings pane. Install the VS Code eslint extension for real-time feedback."
49+
},
50+
{
51+
step: 8,
52+
title: "Do NOT commit .npmrc or yarn.lock changes",
53+
notes: "Changes to .npmrc and yarn.lock from using the public npm registry must not be pushed. These files are configured for the project's Azure Artifacts feed."
54+
}
55+
];

tools/onboarding-mcp/src/index.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3+
import { registerSetupTool } from "./tools/setup.js";
4+
import { registerPrChecklistTool } from "./tools/prChecklist.js";
5+
6+
const server = new McpServer({
7+
name: "cmake-tools-onboarding",
8+
version: "0.1.0"
9+
});
10+
11+
// Register all tools
12+
registerSetupTool(server);
13+
registerPrChecklistTool(server);
14+
15+
// Start the server over stdio
16+
const transport = new StdioServerTransport();
17+
await server.connect(transport);
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { z } from "zod";
2+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3+
import { prRules } from "../data/prRules.js";
4+
5+
export interface ChecklistItem {
6+
rule: string;
7+
status: "pass" | "warn" | "manual_check_required";
8+
hint: string;
9+
}
10+
11+
export function registerPrChecklistTool(server: McpServer): void {
12+
server.registerTool(
13+
"check_pr_readiness",
14+
{
15+
title: "Check PR Readiness",
16+
description:
17+
"Given a free-text description of what a contributor changed, returns a checklist " +
18+
"of PR requirements derived from CONTRIBUTING.md. Each item has a rule, a status " +
19+
'("pass", "warn", or "manual_check_required"), and a hint. Since we cannot ' +
20+
"inspect the actual diff, most items are 'manual_check_required' with a helpful " +
21+
"hint. Items are flagged as 'warn' when the description suggests a potential issue.",
22+
inputSchema: z.object({
23+
changes: z
24+
.string()
25+
.describe("A free-text description of what the contributor changed.")
26+
})
27+
},
28+
async ({ changes }) => {
29+
const lowerChanges = changes.toLowerCase();
30+
31+
const checklist: ChecklistItem[] = prRules.map((rule) => {
32+
let status: ChecklistItem["status"] = "manual_check_required";
33+
34+
// Flag as "warn" if the change description contains any warn keywords
35+
if (
36+
rule.warnKeywords?.some((keyword) =>
37+
lowerChanges.includes(keyword.toLowerCase())
38+
)
39+
) {
40+
status = "warn";
41+
}
42+
43+
return {
44+
rule: rule.rule,
45+
status,
46+
hint: rule.hint
47+
};
48+
});
49+
50+
return {
51+
content: [
52+
{
53+
type: "text" as const,
54+
text: JSON.stringify(checklist, null, 2)
55+
}
56+
]
57+
};
58+
}
59+
);
60+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2+
import { setupSteps } from "../data/setupSteps.js";
3+
4+
export function registerSetupTool(server: McpServer): void {
5+
server.registerTool(
6+
"get_setup_guide",
7+
{
8+
title: "Get Setup Guide",
9+
description:
10+
"Returns an ordered list of setup steps a new contributor needs to follow " +
11+
"to build and run the CMake Tools VS Code extension locally. " +
12+
"Each step includes a number, title, optional command, and optional notes."
13+
},
14+
async () => ({
15+
content: [
16+
{
17+
type: "text" as const,
18+
text: JSON.stringify(setupSteps, null, 2)
19+
}
20+
]
21+
})
22+
);
23+
}

tools/onboarding-mcp/tsconfig.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2022",
4+
"module": "Node16",
5+
"moduleResolution": "Node16",
6+
"outDir": "./dist",
7+
"rootDir": "./src",
8+
"strict": true,
9+
"esModuleInterop": true,
10+
"skipLibCheck": true,
11+
"forceConsistentCasingInFileNames": true,
12+
"declaration": true,
13+
"declarationMap": true,
14+
"sourceMap": true
15+
},
16+
"include": ["src/**/*.ts"],
17+
"exclude": ["node_modules", "dist"]
18+
}

0 commit comments

Comments
 (0)