vcluster-yaml-mcp-server 1.1.1 → 1.2.0
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 +4 -2
- package/package.json +8 -5
- package/src/server-info.js +14 -0
- package/src/server.js +167 -145
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ Run the server locally via npx:
|
|
|
52
52
|
"mcpServers": {
|
|
53
53
|
"vcluster-yaml": {
|
|
54
54
|
"command": "npx",
|
|
55
|
-
"args": ["-y", "vcluster-yaml-mcp-server"]
|
|
55
|
+
"args": ["-y", "vcluster-yaml-mcp-server@latest"]
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
58
|
}
|
|
@@ -287,10 +287,12 @@ npm run start:http
|
|
|
287
287
|
|
|
288
288
|
## Technical Details
|
|
289
289
|
|
|
290
|
-
- **SDK**: `@modelcontextprotocol/sdk` v1.
|
|
290
|
+
- **SDK**: `@modelcontextprotocol/sdk` v1.25.2 using `McpServer` high-level API
|
|
291
291
|
- **Node**: >=18
|
|
292
292
|
- **Transport**: Both stdio (local) and HTTP/SSE (remote)
|
|
293
293
|
- **Dependencies**: `js-yaml` for parsing, `node-jq` for querying, `node-fetch` for GitHub API
|
|
294
|
+
- **Tool Annotations**: All tools include `readOnlyHint`/`destructiveHint` for client optimization
|
|
295
|
+
- **Server Instructions**: Includes instructions for MCP tool search auto mode
|
|
294
296
|
|
|
295
297
|
## Release Process
|
|
296
298
|
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vcluster-yaml-mcp-server",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "MCP server for querying vcluster YAML configurations using jq",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/Piotr1215/vcluster-yaml-mcp"
|
|
8
|
+
},
|
|
5
9
|
"main": "src/index.js",
|
|
6
10
|
"type": "module",
|
|
7
11
|
"bin": {
|
|
8
|
-
"vcluster-yaml-mcp-server": "./src/
|
|
9
|
-
"vcluster-yaml-mcp": "./src/index.js",
|
|
12
|
+
"vcluster-yaml-mcp-server": "./src/index.js",
|
|
10
13
|
"vcluster-yaml": "./src/cli.js"
|
|
11
14
|
},
|
|
12
15
|
"files": [
|
|
@@ -25,14 +28,14 @@
|
|
|
25
28
|
"test:ci": "vitest run tests/ci/",
|
|
26
29
|
"test:all": "vitest run",
|
|
27
30
|
"test:watch": "vitest --exclude tests/integration/**/*.test.js",
|
|
28
|
-
"test:coverage": "vitest run --coverage --exclude tests/integration/**/*.test.js",
|
|
31
|
+
"test:coverage": "vitest run --coverage --exclude tests/integration/**/*.test.js --exclude tests/ci/**/*.test.js --exclude tests/performance.test.js",
|
|
29
32
|
"test:mutation": "stryker run",
|
|
30
33
|
"complexity": "eslint --config eslint.config.complexity.js src/**/*.js",
|
|
31
34
|
"complexity:json": "eslint --config eslint.config.complexity.js --format json --output-file reports/complexity.json src/**/*.js || true",
|
|
32
35
|
"lint:workflows": "actionlint .github/workflows/*.yml"
|
|
33
36
|
},
|
|
34
37
|
"dependencies": {
|
|
35
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
38
|
+
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
36
39
|
"@opentelemetry/api": "^1.9.0",
|
|
37
40
|
"@opentelemetry/auto-instrumentations-node": "^0.66.0",
|
|
38
41
|
"@opentelemetry/exporter-trace-otlp-grpc": "^0.207.0",
|
package/src/server-info.js
CHANGED
|
@@ -70,3 +70,17 @@ export function getMcpServerInfo() {
|
|
|
70
70
|
version: packageJson.version
|
|
71
71
|
};
|
|
72
72
|
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get server options including instructions for MCP clients
|
|
76
|
+
* @returns {Object} MCP server options
|
|
77
|
+
*/
|
|
78
|
+
export function getMcpServerOptions() {
|
|
79
|
+
return {
|
|
80
|
+
capabilities: {
|
|
81
|
+
tools: {},
|
|
82
|
+
resources: {}
|
|
83
|
+
},
|
|
84
|
+
instructions: "vCluster configuration assistant. Use smart-query for any configuration questions (natural language search). Use create-vcluster-config when generating configs - it auto-validates. Use list-versions first to discover available versions. Use validate-config for user-provided YAML. Use extract-validation-rules to understand semantic constraints."
|
|
85
|
+
};
|
|
86
|
+
}
|
package/src/server.js
CHANGED
|
@@ -1,168 +1,190 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
ListToolsRequestSchema,
|
|
4
|
-
CallToolRequestSchema,
|
|
5
|
-
ListResourcesRequestSchema,
|
|
6
|
-
ReadResourceRequestSchema
|
|
7
|
-
} from '@modelcontextprotocol/sdk/types.js';
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
8
2
|
import { githubClient } from './github.js';
|
|
9
|
-
import {
|
|
10
|
-
|
|
3
|
+
import {
|
|
4
|
+
handleCreateConfig,
|
|
5
|
+
handleListVersions,
|
|
6
|
+
handleSmartQuery,
|
|
7
|
+
handleExtractRules,
|
|
8
|
+
handleValidateConfig
|
|
9
|
+
} from './tool-handlers.js';
|
|
10
|
+
import { getMcpServerInfo, getMcpServerOptions, getServerInfo } from './server-info.js';
|
|
11
11
|
|
|
12
12
|
export function createServer() {
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const serverInfo = getMcpServerInfo();
|
|
14
|
+
const serverOptions = getMcpServerOptions();
|
|
15
|
+
|
|
16
|
+
const server = new McpServer(serverInfo, serverOptions);
|
|
17
|
+
|
|
18
|
+
// Register: list-versions
|
|
19
|
+
server.registerTool(
|
|
20
|
+
'list-versions',
|
|
15
21
|
{
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
22
|
+
description: 'DISCOVERY: Find all available vCluster versions. Returns GitHub tags (stable releases) and branches (development versions). Use this to discover what versions are available before querying specific versions.',
|
|
23
|
+
inputSchema: {
|
|
24
|
+
type: 'object',
|
|
25
|
+
properties: {},
|
|
26
|
+
required: []
|
|
27
|
+
},
|
|
28
|
+
annotations: {
|
|
29
|
+
readOnlyHint: true
|
|
19
30
|
}
|
|
31
|
+
},
|
|
32
|
+
async () => {
|
|
33
|
+
const result = await handleListVersions({}, githubClient);
|
|
34
|
+
return result;
|
|
20
35
|
}
|
|
21
36
|
);
|
|
22
37
|
|
|
23
|
-
//
|
|
24
|
-
server.
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
38
|
+
// Register: smart-query
|
|
39
|
+
server.registerTool(
|
|
40
|
+
'smart-query',
|
|
41
|
+
{
|
|
42
|
+
description: 'UNIVERSAL SEARCH: Your go-to tool for finding ANY vCluster configuration! Understands natural language, searches intelligently, and finds related settings. USE THIS FIRST for any config questions! Examples: "show me namespace settings", "how is etcd configured?", "what networking options exist?", "find service CIDR". Searches chart/values.yaml by default.',
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: 'object',
|
|
45
|
+
properties: {
|
|
46
|
+
query: {
|
|
47
|
+
type: 'string',
|
|
48
|
+
description: 'Natural language query (e.g., "namespace syncing", "high availability", "storage options")'
|
|
49
|
+
},
|
|
50
|
+
file: {
|
|
51
|
+
type: 'string',
|
|
52
|
+
description: 'Optional: specific file to search (default: "chart/values.yaml")'
|
|
53
|
+
},
|
|
54
|
+
version: {
|
|
55
|
+
type: 'string',
|
|
56
|
+
description: 'Version tag or branch (e.g., "v0.24.0", "main"). Defaults to "main".'
|
|
34
57
|
}
|
|
35
58
|
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
required: ['query']
|
|
60
|
+
},
|
|
61
|
+
annotations: {
|
|
62
|
+
readOnlyHint: true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
async ({ query, file, version }) => {
|
|
66
|
+
const result = await handleSmartQuery({ query, file, version }, githubClient);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
// Register: create-vcluster-config
|
|
72
|
+
server.registerTool(
|
|
73
|
+
'create-vcluster-config',
|
|
74
|
+
{
|
|
75
|
+
description: 'CONFIG CREATION WORKFLOW: Use this when generating vCluster configurations for users. This tool REQUIRES you to provide the YAML you created and automatically validates it before returning to the user. Returns validation result + formatted config. This ensures every config you create is validated.',
|
|
76
|
+
inputSchema: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {
|
|
79
|
+
yaml_content: {
|
|
80
|
+
type: 'string',
|
|
81
|
+
description: 'The vCluster YAML configuration you generated (required)'
|
|
82
|
+
},
|
|
83
|
+
description: {
|
|
84
|
+
type: 'string',
|
|
85
|
+
description: 'Brief description of what this config does (optional, helpful for user)'
|
|
86
|
+
},
|
|
87
|
+
version: {
|
|
88
|
+
type: 'string',
|
|
89
|
+
description: 'Version tag or branch (e.g., "v0.24.0", "main"). Defaults to "main".'
|
|
56
90
|
}
|
|
57
91
|
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
required: ['yaml_content']
|
|
93
|
+
},
|
|
94
|
+
annotations: {
|
|
95
|
+
readOnlyHint: false
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
async ({ yaml_content, description, version }) => {
|
|
99
|
+
const result = await handleCreateConfig({ yaml_content, description, version }, githubClient);
|
|
100
|
+
return result;
|
|
101
|
+
}
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
// Register: validate-config
|
|
105
|
+
server.registerTool(
|
|
106
|
+
'validate-config',
|
|
107
|
+
{
|
|
108
|
+
description: 'VALIDATION ONLY: Validates existing vCluster YAML (full config or partial snippet) against the schema. Use create-vcluster-config for configs you generate. Use this to validate user-provided configs or files from GitHub.',
|
|
109
|
+
inputSchema: {
|
|
110
|
+
type: 'object',
|
|
111
|
+
properties: {
|
|
112
|
+
file: {
|
|
113
|
+
type: 'string',
|
|
114
|
+
description: 'File path in GitHub repo to validate. Optional if content is provided.'
|
|
115
|
+
},
|
|
116
|
+
content: {
|
|
117
|
+
type: 'string',
|
|
118
|
+
description: 'YAML content to validate (full config or partial snippet)'
|
|
119
|
+
},
|
|
120
|
+
version: {
|
|
121
|
+
type: 'string',
|
|
122
|
+
description: 'Version tag or branch (e.g., "v0.24.0", "main"). Defaults to "main".'
|
|
78
123
|
}
|
|
79
124
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
125
|
+
required: []
|
|
126
|
+
},
|
|
127
|
+
annotations: {
|
|
128
|
+
readOnlyHint: true
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
async ({ file, content, version }) => {
|
|
132
|
+
const result = await handleValidateConfig({ file, content, version }, githubClient);
|
|
133
|
+
return result;
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
// Register: extract-validation-rules
|
|
138
|
+
server.registerTool(
|
|
139
|
+
'extract-validation-rules',
|
|
140
|
+
{
|
|
141
|
+
description: 'AI ASSISTANT: Extract validation rules, constraints, and best practices directly from values.yaml comments. Returns structured rules for AI to understand complex relationships and semantic validations that procedural code cannot handle. USE THIS when you need to understand the "why" behind configurations or validate semantic correctness beyond syntax.',
|
|
142
|
+
inputSchema: {
|
|
143
|
+
type: 'object',
|
|
144
|
+
properties: {
|
|
145
|
+
file: {
|
|
146
|
+
type: 'string',
|
|
147
|
+
description: 'File path in GitHub repo (default: "chart/values.yaml")'
|
|
148
|
+
},
|
|
149
|
+
section: {
|
|
150
|
+
type: 'string',
|
|
151
|
+
description: 'Focus on specific section (e.g., "controlPlane", "sync", "networking")'
|
|
152
|
+
},
|
|
153
|
+
version: {
|
|
154
|
+
type: 'string',
|
|
155
|
+
description: 'Version tag or branch (e.g., "v0.24.0", "main"). Defaults to "main".'
|
|
100
156
|
}
|
|
101
157
|
},
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
section: {
|
|
114
|
-
type: 'string',
|
|
115
|
-
description: 'Focus on specific section (e.g., "controlPlane", "sync", "networking")'
|
|
116
|
-
},
|
|
117
|
-
version: {
|
|
118
|
-
type: 'string',
|
|
119
|
-
description: 'Version tag or branch (e.g., "v0.24.0", "main"). Defaults to "main".'
|
|
120
|
-
}
|
|
121
|
-
},
|
|
122
|
-
required: []
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
]
|
|
126
|
-
};
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
// Tool handler
|
|
130
|
-
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
131
|
-
const { name, arguments: args } = request.params;
|
|
132
|
-
return executeToolHandler(name, args, githubClient);
|
|
133
|
-
});
|
|
158
|
+
required: []
|
|
159
|
+
},
|
|
160
|
+
annotations: {
|
|
161
|
+
readOnlyHint: true
|
|
162
|
+
}
|
|
163
|
+
},
|
|
164
|
+
async ({ file, section, version }) => {
|
|
165
|
+
const result = await handleExtractRules({ file, section, version }, githubClient);
|
|
166
|
+
return result;
|
|
167
|
+
}
|
|
168
|
+
);
|
|
134
169
|
|
|
135
|
-
//
|
|
136
|
-
server.
|
|
137
|
-
|
|
138
|
-
|
|
170
|
+
// Register resource: server://info
|
|
171
|
+
server.registerResource(
|
|
172
|
+
'server-info',
|
|
173
|
+
'server://info',
|
|
174
|
+
{
|
|
175
|
+
description: 'Version, build info, and metadata about this MCP server',
|
|
176
|
+
mimeType: 'application/json'
|
|
177
|
+
},
|
|
178
|
+
async (uri) => ({
|
|
179
|
+
contents: [
|
|
139
180
|
{
|
|
140
|
-
uri:
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
mimeType: 'application/json'
|
|
181
|
+
uri: uri.href,
|
|
182
|
+
mimeType: 'application/json',
|
|
183
|
+
text: JSON.stringify(getServerInfo(), null, 2)
|
|
144
184
|
}
|
|
145
185
|
]
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
150
|
-
const { uri } = request.params;
|
|
151
|
-
|
|
152
|
-
if (uri === 'server://info') {
|
|
153
|
-
return {
|
|
154
|
-
contents: [
|
|
155
|
-
{
|
|
156
|
-
uri: 'server://info',
|
|
157
|
-
mimeType: 'application/json',
|
|
158
|
-
text: JSON.stringify(getServerInfo(), null, 2)
|
|
159
|
-
}
|
|
160
|
-
]
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
throw new Error(`Unknown resource: ${uri}`);
|
|
165
|
-
});
|
|
186
|
+
})
|
|
187
|
+
);
|
|
166
188
|
|
|
167
189
|
return server;
|
|
168
190
|
}
|