dotnet-ai-mcp-server 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +27 -76
- package/bin/cli.js +21 -83
- package/package.json +1 -1
- package/scripts/postinstall.js +82 -63
package/README.md
CHANGED
|
@@ -1,99 +1,50 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dotnet-ai-mcp-server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
MCP Server for .NET AI development - provides real code samples from Semantic Kernel, OpenAI .NET, MCP C# SDK, and more.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g dotnet-ai-mcp-server
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
Or use with npx (no installation needed):
|
|
10
12
|
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
"mcpServers": {
|
|
14
|
-
"dotnet-ai": {
|
|
15
|
-
"command": "npx",
|
|
16
|
-
"args": ["-y", "dotnet-ai-mcp-server"]
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
13
|
+
```bash
|
|
14
|
+
npx dotnet-ai-mcp-server
|
|
20
15
|
```
|
|
21
16
|
|
|
22
|
-
|
|
17
|
+
## Usage with Claude Desktop
|
|
23
18
|
|
|
24
|
-
Add to your
|
|
19
|
+
Add to your `claude_desktop_config.json`:
|
|
25
20
|
|
|
26
21
|
```json
|
|
27
22
|
{
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
"args": ["-y", "dotnet-ai-mcp-server"]
|
|
33
|
-
}
|
|
23
|
+
"mcpServers": {
|
|
24
|
+
"dotnet-ai": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "dotnet-ai-mcp-server"]
|
|
34
27
|
}
|
|
35
28
|
}
|
|
36
29
|
}
|
|
37
30
|
```
|
|
38
31
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
- Node.js 16+ - For npx
|
|
43
|
-
|
|
44
|
-
## What This Does
|
|
45
|
-
|
|
46
|
-
This MCP server provides real, up-to-date code samples from the .NET AI ecosystem:
|
|
32
|
+
### Config file locations:
|
|
33
|
+
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
34
|
+
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
47
35
|
|
|
48
|
-
|
|
49
|
-
- **OpenAI .NET SDK** - Official OpenAI client
|
|
50
|
-
- **MCP C# SDK** - Model Context Protocol for .NET
|
|
51
|
-
- **Microsoft.Extensions.AI** - AI abstractions
|
|
52
|
-
- **Anthropic SDK** - Claude SDK for .NET
|
|
53
|
-
- **Google GenAI** - Gemini SDK for .NET
|
|
54
|
-
- **Vector DBs** - Pinecone, Qdrant, Weaviate, Redis
|
|
36
|
+
## Features
|
|
55
37
|
|
|
56
|
-
|
|
38
|
+
- **Real code samples** from official Microsoft repositories
|
|
39
|
+
- **GitHub integration** - fetches live code from Semantic Kernel, OpenAI .NET, MCP C# SDK, and more
|
|
40
|
+
- **Microsoft Learn docs** - searches official documentation
|
|
41
|
+
- **No .NET SDK required** - self-contained executable
|
|
57
42
|
|
|
58
|
-
|
|
43
|
+
## Supported Platforms
|
|
59
44
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|------|-------------|
|
|
64
|
-
| `Start_DotNet_Reasoning` | Entry point - lists tracked repositories |
|
|
65
|
-
| `GitHubGetFolders` | Shows folder structure |
|
|
66
|
-
| `GitHubListFiles` | Lists files in folders |
|
|
67
|
-
| `GitHubFetchFiles` | Fetches actual code |
|
|
68
|
-
| `MicrosoftDocsSearch` | Searches Microsoft Learn |
|
|
69
|
-
| `MicrosoftDocsFetch` | Fetches documentation |
|
|
70
|
-
| `MicrosoftCodeSampleSearch` | Finds code samples |
|
|
71
|
-
|
|
72
|
-
## How It Works
|
|
73
|
-
|
|
74
|
-
1. The npm package installs the .NET global tool (`dotnet tool install -g DotNetAIMcpServer`)
|
|
75
|
-
2. When invoked via npx, it runs the dotnet tool which communicates via stdio
|
|
76
|
-
3. The tool fetches live code from GitHub and Microsoft Learn
|
|
77
|
-
|
|
78
|
-
## Manual Installation
|
|
79
|
-
|
|
80
|
-
If you prefer to install the dotnet tool directly:
|
|
81
|
-
|
|
82
|
-
```bash
|
|
83
|
-
dotnet tool install -g DotNetAIMcpServer
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
Then configure your MCP client to use:
|
|
87
|
-
|
|
88
|
-
```json
|
|
89
|
-
{
|
|
90
|
-
"mcpServers": {
|
|
91
|
-
"dotnet-ai": {
|
|
92
|
-
"command": "dotnet-ai-mcp"
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
```
|
|
45
|
+
- macOS (Intel & Apple Silicon)
|
|
46
|
+
- Linux (x64 & ARM64)
|
|
47
|
+
- Windows (x64)
|
|
97
48
|
|
|
98
49
|
## License
|
|
99
50
|
|
package/bin/cli.js
CHANGED
|
@@ -1,93 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { spawn } = require('child_process');
|
|
4
|
-
const
|
|
5
|
-
const { join } = require('path');
|
|
4
|
+
const path = require('path');
|
|
6
5
|
const os = require('os');
|
|
6
|
+
const fs = require('fs');
|
|
7
7
|
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const isWindows = os.platform() === 'win32';
|
|
9
|
+
const binaryName = isWindows ? 'dotnet-ai-mcp-server.exe' : 'dotnet-ai-mcp-server';
|
|
10
|
+
const binaryPath = path.join(__dirname, binaryName);
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
});
|
|
12
|
+
if (!fs.existsSync(binaryPath)) {
|
|
13
|
+
console.error('Binary not found. Please reinstall the package:');
|
|
14
|
+
console.error(' npm uninstall -g dotnet-ai-mcp-server');
|
|
15
|
+
console.error(' npm install -g dotnet-ai-mcp-server');
|
|
16
|
+
process.exit(1);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
proc.stdout.on('data', (data) => { output += data.toString(); });
|
|
24
|
-
proc.on('close', () => {
|
|
25
|
-
resolve(output.toLowerCase().includes(NUGET_PACKAGE.toLowerCase()));
|
|
26
|
-
});
|
|
27
|
-
proc.on('error', () => resolve(false));
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function installTool() {
|
|
32
|
-
console.error(`Installing ${NUGET_PACKAGE}...`);
|
|
33
|
-
return new Promise((resolve, reject) => {
|
|
34
|
-
const proc = spawn('dotnet', ['tool', 'install', '-g', NUGET_PACKAGE], {
|
|
35
|
-
stdio: 'inherit'
|
|
36
|
-
});
|
|
37
|
-
proc.on('close', (code) => {
|
|
38
|
-
if (code === 0) resolve();
|
|
39
|
-
else reject(new Error(`Failed to install ${NUGET_PACKAGE}`));
|
|
40
|
-
});
|
|
41
|
-
proc.on('error', reject);
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
async function runTool() {
|
|
46
|
-
const isWindows = os.platform() === 'win32';
|
|
47
|
-
const toolPath = isWindows
|
|
48
|
-
? join(os.homedir(), '.dotnet', 'tools', `${TOOL_NAME}.exe`)
|
|
49
|
-
: join(os.homedir(), '.dotnet', 'tools', TOOL_NAME);
|
|
50
|
-
|
|
51
|
-
// Always use full path for reliability
|
|
52
|
-
const proc = spawn(toolPath, [], {
|
|
53
|
-
stdio: 'inherit',
|
|
54
|
-
shell: false
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
proc.on('error', (err) => {
|
|
58
|
-
console.error(`Error running ${TOOL_NAME}: ${err.message}`);
|
|
59
|
-
console.error(`Tried path: ${toolPath}`);
|
|
60
|
-
console.error('Make sure the dotnet tool is installed: dotnet tool install -g DotNetAIMcpServer');
|
|
61
|
-
process.exit(1);
|
|
62
|
-
});
|
|
19
|
+
const proc = spawn(binaryPath, process.argv.slice(2), {
|
|
20
|
+
stdio: 'inherit',
|
|
21
|
+
shell: false
|
|
22
|
+
});
|
|
63
23
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
async function main() {
|
|
70
|
-
try {
|
|
71
|
-
// Check if .NET is installed
|
|
72
|
-
const dotnetInstalled = await checkDotnetInstalled();
|
|
73
|
-
if (!dotnetInstalled) {
|
|
74
|
-
console.error('ERROR: .NET SDK is not installed.');
|
|
75
|
-
console.error('Please install .NET 9.0 SDK from: https://dotnet.microsoft.com/download');
|
|
76
|
-
process.exit(1);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Check if the tool is installed
|
|
80
|
-
const toolInstalled = await checkToolInstalled();
|
|
81
|
-
if (!toolInstalled) {
|
|
82
|
-
await installTool();
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Run the tool
|
|
86
|
-
await runTool();
|
|
87
|
-
} catch (error) {
|
|
88
|
-
console.error(`Error: ${error.message}`);
|
|
89
|
-
process.exit(1);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
24
|
+
proc.on('error', (err) => {
|
|
25
|
+
console.error(`Failed to start server: ${err.message}`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
});
|
|
92
28
|
|
|
93
|
-
|
|
29
|
+
proc.on('close', (code) => {
|
|
30
|
+
process.exit(code || 0);
|
|
31
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dotnet-ai-mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.3",
|
|
4
4
|
"description": "MCP Server for .NET AI development - provides real code samples from Semantic Kernel, OpenAI .NET, MCP C# SDK, and more",
|
|
5
5
|
"bin": {
|
|
6
6
|
"dotnet-ai-mcp-server": "bin/cli.js"
|
package/scripts/postinstall.js
CHANGED
|
@@ -1,85 +1,104 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const { execSync } = require('child_process');
|
|
4
8
|
|
|
5
|
-
const
|
|
9
|
+
const REPO = 'ArbelH/dotnet-ai-mcp-server';
|
|
10
|
+
const VERSION = require('../package.json').version;
|
|
6
11
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
proc.on('close', (code) => resolve(code === 0));
|
|
11
|
-
proc.on('error', () => resolve(false));
|
|
12
|
-
});
|
|
13
|
-
}
|
|
12
|
+
function getPlatformInfo() {
|
|
13
|
+
const platform = os.platform();
|
|
14
|
+
const arch = os.arch();
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
const platformMap = {
|
|
17
|
+
'darwin-x64': 'dotnet-ai-mcp-server-darwin-x64',
|
|
18
|
+
'darwin-arm64': 'dotnet-ai-mcp-server-darwin-arm64',
|
|
19
|
+
'linux-x64': 'dotnet-ai-mcp-server-linux-x64',
|
|
20
|
+
'linux-arm64': 'dotnet-ai-mcp-server-linux-arm64',
|
|
21
|
+
'win32-x64': 'dotnet-ai-mcp-server-win-x64.exe',
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const key = `${platform}-${arch}`;
|
|
25
|
+
const binaryName = platformMap[key];
|
|
26
|
+
|
|
27
|
+
if (!binaryName) {
|
|
28
|
+
console.error(`Unsupported platform: ${platform}-${arch}`);
|
|
29
|
+
console.error('Supported platforms: darwin-x64, darwin-arm64, linux-x64, linux-arm64, win32-x64');
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return { binaryName, isWindows: platform === 'win32' };
|
|
25
34
|
}
|
|
26
35
|
|
|
27
|
-
|
|
28
|
-
console.log(`Installing ${NUGET_PACKAGE} dotnet tool...`);
|
|
36
|
+
function downloadFile(url, dest) {
|
|
29
37
|
return new Promise((resolve, reject) => {
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
const follow = (url, redirectCount = 0) => {
|
|
39
|
+
if (redirectCount > 5) {
|
|
40
|
+
reject(new Error('Too many redirects'));
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
https.get(url, { headers: { 'User-Agent': 'dotnet-ai-mcp-server-npm' } }, (response) => {
|
|
45
|
+
if (response.statusCode >= 300 && response.statusCode < 400 && response.headers.location) {
|
|
46
|
+
follow(response.headers.location, redirectCount + 1);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (response.statusCode !== 200) {
|
|
51
|
+
reject(new Error(`Failed to download: ${response.statusCode}`));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const file = fs.createWriteStream(dest);
|
|
56
|
+
response.pipe(file);
|
|
57
|
+
file.on('finish', () => {
|
|
58
|
+
file.close();
|
|
59
|
+
resolve();
|
|
41
60
|
});
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
resolve();
|
|
46
|
-
} else {
|
|
47
|
-
reject(new Error(`Failed to install/update ${NUGET_PACKAGE}`));
|
|
48
|
-
}
|
|
61
|
+
file.on('error', (err) => {
|
|
62
|
+
fs.unlink(dest, () => {});
|
|
63
|
+
reject(err);
|
|
49
64
|
});
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
}).on('error', reject);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
follow(url);
|
|
54
69
|
});
|
|
55
70
|
}
|
|
56
71
|
|
|
57
72
|
async function main() {
|
|
73
|
+
const { binaryName, isWindows } = getPlatformInfo();
|
|
74
|
+
const binDir = path.join(__dirname, '..', 'bin');
|
|
75
|
+
const binaryPath = path.join(binDir, isWindows ? 'dotnet-ai-mcp-server.exe' : 'dotnet-ai-mcp-server');
|
|
76
|
+
|
|
77
|
+
// Skip if binary already exists
|
|
78
|
+
if (fs.existsSync(binaryPath)) {
|
|
79
|
+
console.log('Binary already exists, skipping download.');
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const downloadUrl = `https://github.com/${REPO}/releases/download/v${VERSION}/${binaryName}`;
|
|
84
|
+
|
|
85
|
+
console.log(`Downloading ${binaryName}...`);
|
|
86
|
+
console.log(`URL: ${downloadUrl}`);
|
|
87
|
+
|
|
58
88
|
try {
|
|
59
|
-
|
|
60
|
-
const dotnetInstalled = await checkDotnetInstalled();
|
|
61
|
-
if (!dotnetInstalled) {
|
|
62
|
-
console.log('\n========================================');
|
|
63
|
-
console.log(' .NET SDK Required');
|
|
64
|
-
console.log('========================================');
|
|
65
|
-
console.log('This package requires .NET 9.0 SDK.');
|
|
66
|
-
console.log('Please install from: https://dotnet.microsoft.com/download');
|
|
67
|
-
console.log('========================================\n');
|
|
68
|
-
return; // Don't fail, just warn
|
|
69
|
-
}
|
|
89
|
+
await downloadFile(downloadUrl, binaryPath);
|
|
70
90
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
if (toolInstalled) {
|
|
74
|
-
console.log(`${NUGET_PACKAGE} is already installed.`);
|
|
75
|
-
return;
|
|
91
|
+
if (!isWindows) {
|
|
92
|
+
fs.chmodSync(binaryPath, 0o755);
|
|
76
93
|
}
|
|
77
94
|
|
|
78
|
-
|
|
79
|
-
await installTool();
|
|
95
|
+
console.log('Download complete!');
|
|
80
96
|
} catch (error) {
|
|
81
|
-
console.error(`
|
|
82
|
-
console.error('
|
|
97
|
+
console.error(`Failed to download binary: ${error.message}`);
|
|
98
|
+
console.error('');
|
|
99
|
+
console.error('You may need to download it manually from:');
|
|
100
|
+
console.error(`https://github.com/${REPO}/releases`);
|
|
101
|
+
process.exit(1);
|
|
83
102
|
}
|
|
84
103
|
}
|
|
85
104
|
|