veryfront 0.1.141 → 0.1.142
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/esm/cli/mcp/jsonrpc.d.ts +33 -1
- package/esm/cli/mcp/jsonrpc.d.ts.map +1 -1
- package/esm/cli/mcp/jsonrpc.js +63 -4
- package/esm/cli/mcp/remote-file-tools.d.ts.map +1 -1
- package/esm/cli/mcp/remote-file-tools.js +39 -0
- package/esm/cli/mcp/server.d.ts.map +1 -1
- package/esm/cli/mcp/server.js +57 -34
- package/esm/cli/mcp/standalone.d.ts.map +1 -1
- package/esm/cli/mcp/standalone.js +24 -11
- package/esm/cli/mcp/tools/catalog-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/catalog-tools.js +15 -5
- package/esm/cli/mcp/tools/cicd-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/cicd-tools.js +8 -0
- package/esm/cli/mcp/tools/dev-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/dev-tools.js +32 -10
- package/esm/cli/mcp/tools/introspection-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/introspection-tools.js +6 -2
- package/esm/cli/mcp/tools/project-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/project-tools.js +12 -4
- package/esm/cli/mcp/tools/scaffold-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/scaffold-tools.js +6 -2
- package/esm/cli/mcp/tools/skill-tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools/skill-tools.js +6 -2
- package/esm/cli/mcp/tools.d.ts.map +1 -1
- package/esm/cli/mcp/tools.js +36 -16
- package/esm/deno.js +1 -1
- package/esm/src/agent/runtime/index.js +1 -1
- package/esm/src/agent/runtime/tool-helpers.d.ts.map +1 -1
- package/esm/src/agent/runtime/tool-helpers.js +59 -30
- package/esm/src/agent/schemas/agent.schema.d.ts +4 -4
- package/esm/src/channels/invoke.d.ts +4 -4
- package/esm/src/issues/mcp.d.ts.map +1 -1
- package/esm/src/issues/mcp.js +39 -10
- package/esm/src/mcp/index.d.ts +1 -1
- package/esm/src/mcp/index.d.ts.map +1 -1
- package/esm/src/mcp/server.d.ts.map +1 -1
- package/esm/src/mcp/server.js +85 -25
- package/esm/src/mcp/types.d.ts +22 -0
- package/esm/src/mcp/types.d.ts.map +1 -1
- package/esm/src/tool/types.d.ts +5 -0
- package/esm/src/tool/types.d.ts.map +1 -1
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/esm/src/workflow/schemas/workflow.schema.d.ts +6 -6
- package/package.json +1 -1
- package/src/cli/mcp/jsonrpc.ts +72 -4
- package/src/cli/mcp/remote-file-tools.ts +39 -0
- package/src/cli/mcp/server.ts +66 -33
- package/src/cli/mcp/standalone.ts +28 -10
- package/src/cli/mcp/tools/catalog-tools.ts +15 -5
- package/src/cli/mcp/tools/cicd-tools.ts +8 -0
- package/src/cli/mcp/tools/dev-tools.ts +34 -10
- package/src/cli/mcp/tools/introspection-tools.ts +7 -2
- package/src/cli/mcp/tools/project-tools.ts +12 -4
- package/src/cli/mcp/tools/scaffold-tools.ts +6 -2
- package/src/cli/mcp/tools/skill-tools.ts +6 -2
- package/src/cli/mcp/tools.ts +52 -16
- package/src/deno.js +1 -1
- package/src/src/agent/runtime/index.ts +1 -1
- package/src/src/agent/runtime/tool-helpers.ts +86 -36
- package/src/src/issues/mcp.ts +43 -10
- package/src/src/mcp/index.ts +7 -1
- package/src/src/mcp/server.ts +92 -31
- package/src/src/mcp/types.ts +24 -0
- package/src/src/tool/types.ts +7 -0
- package/src/src/utils/version-constant.ts +1 -1
package/src/cli/mcp/server.ts
CHANGED
|
@@ -13,11 +13,14 @@ import { createHttpServer, type HttpServer } from "../../src/platform/compat/htt
|
|
|
13
13
|
import type { StdinReader } from "../../src/platform/index.js";
|
|
14
14
|
import { withSpan } from "../../src/observability/tracing/otlp-setup.js";
|
|
15
15
|
import { createIssuesManager } from "../../src/issues/index.js";
|
|
16
|
+
import type { ToolListEntry } from "../../src/mcp/index.js";
|
|
16
17
|
import { getErrorCollector, getLogBuffer } from "../../src/observability/index.js";
|
|
17
18
|
import { allTools, getTool, setServerStartTime } from "./tools.js";
|
|
18
19
|
import { startStdioJsonRpc } from "./stdio.js";
|
|
19
20
|
import {
|
|
21
|
+
buildInitializeResult,
|
|
20
22
|
errorResponse,
|
|
23
|
+
JsonRpcError,
|
|
21
24
|
type JSONRPCRequest,
|
|
22
25
|
JSONRPCRequestSchema,
|
|
23
26
|
type JSONRPCResponse,
|
|
@@ -121,6 +124,17 @@ export class MCPDevServer {
|
|
|
121
124
|
|
|
122
125
|
if (req.method === "OPTIONS") return new dntShim.Response(null, { status: 204, headers });
|
|
123
126
|
|
|
127
|
+
if (origin && !isAllowedOrigin) {
|
|
128
|
+
return new dntShim.Response(
|
|
129
|
+
JSON.stringify({
|
|
130
|
+
jsonrpc: "2.0",
|
|
131
|
+
id: null,
|
|
132
|
+
error: { code: -32600, message: "Forbidden: Origin not allowed" },
|
|
133
|
+
}),
|
|
134
|
+
{ status: 403, headers },
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
124
138
|
if (url.pathname !== "/mcp") {
|
|
125
139
|
return new dntShim.Response(JSON.stringify({ error: "Not found. MCP endpoint is at /mcp" }), {
|
|
126
140
|
status: 404,
|
|
@@ -168,6 +182,8 @@ export class MCPDevServer {
|
|
|
168
182
|
switch (method) {
|
|
169
183
|
case "initialize":
|
|
170
184
|
return Promise.resolve(this.handleInitialize(params));
|
|
185
|
+
case "notifications/initialized":
|
|
186
|
+
return Promise.resolve({});
|
|
171
187
|
case "tools/list":
|
|
172
188
|
return Promise.resolve(this.handleToolsList());
|
|
173
189
|
case "tools/call":
|
|
@@ -185,53 +201,70 @@ export class MCPDevServer {
|
|
|
185
201
|
}
|
|
186
202
|
}
|
|
187
203
|
|
|
188
|
-
private handleInitialize(
|
|
189
|
-
return
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
204
|
+
private handleInitialize(params: unknown): unknown {
|
|
205
|
+
return buildInitializeResult(
|
|
206
|
+
params,
|
|
207
|
+
{
|
|
208
|
+
name: this.config.serverName ?? "veryfront-dev",
|
|
209
|
+
title: "Veryfront Dev MCP Server",
|
|
210
|
+
version: this.config.serverVersion ?? "1.0.0",
|
|
211
|
+
description:
|
|
212
|
+
"Veryfront development server tools for real-time errors, logs, HMR, and scaffolding",
|
|
195
213
|
},
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
version: this.config.serverVersion,
|
|
199
|
-
},
|
|
200
|
-
};
|
|
214
|
+
"Veryfront dev MCP server provides development tools. Use vf_get_errors to check for code errors, vf_get_logs for server logs, and vf_trigger_hmr for hot module reload.",
|
|
215
|
+
);
|
|
201
216
|
}
|
|
202
217
|
|
|
203
|
-
private handleToolsList():
|
|
218
|
+
private handleToolsList(): { tools: ToolListEntry[] } {
|
|
204
219
|
return {
|
|
205
|
-
tools: allTools.map((tool) =>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
220
|
+
tools: allTools.map((tool) => {
|
|
221
|
+
const entry: ToolListEntry = {
|
|
222
|
+
name: tool.name,
|
|
223
|
+
description: tool.description,
|
|
224
|
+
inputSchema: this.zodToJsonSchema(tool.inputSchema),
|
|
225
|
+
};
|
|
226
|
+
if (tool.title) entry.title = tool.title;
|
|
227
|
+
if (tool.annotations) entry.annotations = tool.annotations;
|
|
228
|
+
return entry;
|
|
229
|
+
}),
|
|
210
230
|
};
|
|
211
231
|
}
|
|
212
232
|
|
|
213
233
|
private handleToolsCall(params: unknown): Promise<unknown> {
|
|
214
|
-
const { name, arguments: args } = ToolsCallParamsSchema.parse(params);
|
|
234
|
+
const { name: toolName, arguments: args } = ToolsCallParamsSchema.parse(params);
|
|
235
|
+
|
|
236
|
+
const tool = getTool(toolName);
|
|
237
|
+
if (!tool) {
|
|
238
|
+
throw new JsonRpcError(-32602, `Unknown tool: ${toolName}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
let input: unknown;
|
|
242
|
+
try {
|
|
243
|
+
input = tool.inputSchema.parse(args ?? {});
|
|
244
|
+
} catch (error) {
|
|
245
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
246
|
+
throw new JsonRpcError(-32602, `Invalid arguments for tool ${toolName}: ${message}`);
|
|
247
|
+
}
|
|
215
248
|
|
|
216
249
|
return withSpan(
|
|
217
250
|
"cli.mcp.handleToolsCall",
|
|
218
251
|
async () => {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
const input = tool.inputSchema.parse(args ?? {});
|
|
223
|
-
const result = await tool.execute(input);
|
|
252
|
+
try {
|
|
253
|
+
const result = await tool.execute(input);
|
|
224
254
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
255
|
+
return {
|
|
256
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
257
|
+
isError: false,
|
|
258
|
+
};
|
|
259
|
+
} catch (error) {
|
|
260
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
261
|
+
return {
|
|
262
|
+
content: [{ type: "text", text: message }],
|
|
263
|
+
isError: true,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
233
266
|
},
|
|
234
|
-
{ "mcp.tool.name":
|
|
267
|
+
{ "mcp.tool.name": toolName },
|
|
235
268
|
);
|
|
236
269
|
}
|
|
237
270
|
|
|
@@ -11,7 +11,9 @@ import type { StdinReader } from "../../src/platform/index.js";
|
|
|
11
11
|
import { DevServerClient } from "./dev-server-client.js";
|
|
12
12
|
import { startStdioJsonRpc } from "./stdio.js";
|
|
13
13
|
import {
|
|
14
|
+
buildInitializeResult,
|
|
14
15
|
errorResponse,
|
|
16
|
+
JsonRpcError,
|
|
15
17
|
type JSONRPCRequest,
|
|
16
18
|
JSONRPCRequestSchema,
|
|
17
19
|
type JSONRPCResponse,
|
|
@@ -79,11 +81,16 @@ export class StandaloneMCPServer {
|
|
|
79
81
|
private dispatchMethod(method: string, params: unknown): Promise<unknown> {
|
|
80
82
|
switch (method) {
|
|
81
83
|
case "initialize":
|
|
82
|
-
return Promise.resolve(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
return Promise.resolve(buildInitializeResult(
|
|
85
|
+
params,
|
|
86
|
+
{
|
|
87
|
+
name: "veryfront-mcp",
|
|
88
|
+
title: "Veryfront Standalone MCP Server",
|
|
89
|
+
version: "1.0.0",
|
|
90
|
+
description: "Veryfront standalone MCP server for CLI-based development tools",
|
|
91
|
+
},
|
|
92
|
+
"Veryfront standalone MCP server provides development tools. Use vf_get_errors to check for code errors, vf_get_logs for server logs, and vf_get_status for dev server health.",
|
|
93
|
+
));
|
|
87
94
|
case "notifications/initialized":
|
|
88
95
|
return Promise.resolve({});
|
|
89
96
|
case "tools/list":
|
|
@@ -110,13 +117,24 @@ export class StandaloneMCPServer {
|
|
|
110
117
|
}
|
|
111
118
|
|
|
112
119
|
private async handleToolsCall(params: unknown): Promise<unknown> {
|
|
113
|
-
const { name, arguments: args } = ToolsCallParamsSchema.parse(params);
|
|
120
|
+
const { name: toolName, arguments: args } = ToolsCallParamsSchema.parse(params);
|
|
114
121
|
|
|
115
|
-
const tool = this.tools.find((t) => t.name ===
|
|
116
|
-
if (!tool) throw new
|
|
122
|
+
const tool = this.tools.find((t) => t.name === toolName);
|
|
123
|
+
if (!tool) throw new JsonRpcError(-32602, `Unknown tool: ${toolName}`);
|
|
117
124
|
|
|
118
|
-
|
|
119
|
-
|
|
125
|
+
try {
|
|
126
|
+
const result = await tool.execute(args ?? {});
|
|
127
|
+
return {
|
|
128
|
+
content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
|
|
129
|
+
isError: false,
|
|
130
|
+
};
|
|
131
|
+
} catch (error) {
|
|
132
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
133
|
+
return {
|
|
134
|
+
content: [{ type: "text", text: message }],
|
|
135
|
+
isError: true,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
120
138
|
}
|
|
121
139
|
|
|
122
140
|
private handleResourcesList(): unknown {
|
|
@@ -334,8 +334,10 @@ type ListExamplesInput = z.infer<typeof listExamplesInput>;
|
|
|
334
334
|
|
|
335
335
|
export const vfListExamples: MCPTool<ListExamplesInput, ExampleInfo[]> = {
|
|
336
336
|
name: "vf_list_examples",
|
|
337
|
+
title: "List Examples",
|
|
338
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
337
339
|
description:
|
|
338
|
-
"
|
|
340
|
+
"Use this when you need to browse example projects that demonstrate Veryfront features and integrations. Returns an array of example info with name, description, and category. Do not use for project templates — use vf_list_templates instead.",
|
|
339
341
|
inputSchema: listExamplesInput,
|
|
340
342
|
execute: () => Promise.resolve(EXAMPLES),
|
|
341
343
|
};
|
|
@@ -350,8 +352,10 @@ type ListTemplatesInput = z.infer<typeof listTemplatesInput>;
|
|
|
350
352
|
|
|
351
353
|
export const vfListTemplates: MCPTool<ListTemplatesInput, TemplateInfo[]> = {
|
|
352
354
|
name: "vf_list_templates",
|
|
355
|
+
title: "List Templates",
|
|
356
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: true }, // openWorldHint: templates come from remote catalog API
|
|
353
357
|
description:
|
|
354
|
-
"
|
|
358
|
+
"Use this when you need to list available project templates for creating new projects. Returns an array of template info with name and description. Do not use for example projects — use vf_list_examples instead.",
|
|
355
359
|
inputSchema: listTemplatesInput,
|
|
356
360
|
execute: () => Promise.resolve(TEMPLATES),
|
|
357
361
|
};
|
|
@@ -372,8 +376,10 @@ type ListIntegrationsInput = z.infer<typeof listIntegrationsInput>;
|
|
|
372
376
|
|
|
373
377
|
export const vfListIntegrations: MCPTool<ListIntegrationsInput, IntegrationInfo[]> = {
|
|
374
378
|
name: "vf_list_integrations",
|
|
379
|
+
title: "List Integrations",
|
|
380
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
375
381
|
description:
|
|
376
|
-
"
|
|
382
|
+
"Use this when you need to list available service integrations (Gmail, Slack, GitHub, etc.) that can be added to AI projects. Returns an array of integration info with name, category, and description. Do not use for adding integrations to a project — use vf_create_project with the integrations parameter instead.",
|
|
377
383
|
inputSchema: listIntegrationsInput,
|
|
378
384
|
execute: (input) => {
|
|
379
385
|
const { category } = input;
|
|
@@ -392,8 +398,10 @@ type ListUsecasesInput = z.infer<typeof listUsecasesInput>;
|
|
|
392
398
|
|
|
393
399
|
export const vfListUsecases: MCPTool<ListUsecasesInput, UsecaseInfo[]> = {
|
|
394
400
|
name: "vf_list_usecases",
|
|
401
|
+
title: "List Use Cases",
|
|
402
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
395
403
|
description:
|
|
396
|
-
"
|
|
404
|
+
"Use this when you need to browse pre-configured use-case templates with recommended integrations and UI layouts. Returns an array of use-case info with name, integrations, and layout. Do not use for raw templates — use vf_list_templates instead.",
|
|
397
405
|
inputSchema: listUsecasesInput,
|
|
398
406
|
execute: () => Promise.resolve(USECASES),
|
|
399
407
|
};
|
|
@@ -438,8 +446,10 @@ interface CreateProjectResult {
|
|
|
438
446
|
|
|
439
447
|
export const vfCreateProject: MCPTool<CreateProjectInput, CreateProjectResult> = {
|
|
440
448
|
name: "vf_create_project",
|
|
449
|
+
title: "Create Project",
|
|
450
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
441
451
|
description:
|
|
442
|
-
"
|
|
452
|
+
"Use this when you need to create a new Veryfront project from a template. Returns the project directory and next steps. Do not use for scaffolding individual files — use vf_scaffold instead.",
|
|
443
453
|
inputSchema: createProjectInput,
|
|
444
454
|
execute: (input) =>
|
|
445
455
|
withSpan(
|
|
@@ -8,6 +8,8 @@ const getPipelineStatusInput = z.object({
|
|
|
8
8
|
|
|
9
9
|
const vfGetPipelineStatus: MCPTool = {
|
|
10
10
|
name: "vf_get_pipeline_status",
|
|
11
|
+
title: "Pipeline Status",
|
|
12
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
11
13
|
description: "Get the current build/deploy pipeline state for a project environment.",
|
|
12
14
|
inputSchema: getPipelineStatusInput,
|
|
13
15
|
execute: async (input: { projectSlug: string; environment: string }) => {
|
|
@@ -27,6 +29,8 @@ const getDeployHistoryInput = z.object({
|
|
|
27
29
|
|
|
28
30
|
const vfGetDeployHistory: MCPTool = {
|
|
29
31
|
name: "vf_get_deploy_history",
|
|
32
|
+
title: "Deploy History",
|
|
33
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
30
34
|
description: "List recent deployments with status, version, URL, and timestamp.",
|
|
31
35
|
inputSchema: getDeployHistoryInput,
|
|
32
36
|
execute: async (input: { projectSlug: string; limit: number }) => {
|
|
@@ -45,6 +49,8 @@ const getBuildLogsInput = z.object({
|
|
|
45
49
|
|
|
46
50
|
const vfGetBuildLogs: MCPTool = {
|
|
47
51
|
name: "vf_get_build_logs",
|
|
52
|
+
title: "Build Logs",
|
|
53
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
48
54
|
description: "Get build logs from an active or recent build/deployment.",
|
|
49
55
|
inputSchema: getBuildLogsInput,
|
|
50
56
|
execute: async (input: { projectSlug: string; deployId?: string }) => {
|
|
@@ -64,6 +70,8 @@ const triggerDeployInput = z.object({
|
|
|
64
70
|
|
|
65
71
|
const vfTriggerDeploy: MCPTool = {
|
|
66
72
|
name: "vf_trigger_deploy",
|
|
73
|
+
title: "Trigger Deploy",
|
|
74
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
67
75
|
description:
|
|
68
76
|
"Trigger a deployment to an environment. Returns a deployment ID for status tracking.",
|
|
69
77
|
inputSchema: triggerDeployInput,
|
|
@@ -20,7 +20,7 @@ const hotReloadInput = z.object({
|
|
|
20
20
|
file: z
|
|
21
21
|
.string()
|
|
22
22
|
.optional()
|
|
23
|
-
.describe("Specific file to trigger reload for
|
|
23
|
+
.describe("Specific file to trigger reload for. Example: 'app/page.tsx'. Omit to reload all."),
|
|
24
24
|
});
|
|
25
25
|
|
|
26
26
|
type HotReloadInput = z.infer<typeof hotReloadInput>;
|
|
@@ -32,8 +32,15 @@ interface HotReloadResult {
|
|
|
32
32
|
|
|
33
33
|
export const vfHotReload: MCPTool<HotReloadInput, HotReloadResult> = {
|
|
34
34
|
name: "vf_hot_reload",
|
|
35
|
+
title: "Hot Reload",
|
|
36
|
+
annotations: {
|
|
37
|
+
readOnlyHint: false,
|
|
38
|
+
destructiveHint: false,
|
|
39
|
+
idempotentHint: true,
|
|
40
|
+
openWorldHint: false,
|
|
41
|
+
},
|
|
35
42
|
description:
|
|
36
|
-
"
|
|
43
|
+
"Use this when you need to signal that a hot reload should occur. Note: currently a no-op stub that returns success without triggering an actual reload. For file-level HMR that sends a WebSocket update, use vf_trigger_hmr instead.",
|
|
37
44
|
inputSchema: hotReloadInput,
|
|
38
45
|
execute: () =>
|
|
39
46
|
Promise.resolve({
|
|
@@ -72,8 +79,10 @@ interface DebugContextResult {
|
|
|
72
79
|
|
|
73
80
|
export const vfGetDebugContext: MCPTool<GetDebugContextInput, DebugContextResult> = {
|
|
74
81
|
name: "vf_get_debug_context",
|
|
82
|
+
title: "Debug Context",
|
|
83
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
75
84
|
description:
|
|
76
|
-
"
|
|
85
|
+
"Use this when you need the dev server's debug context including project slug, environment, request context mode, and multi-project configuration. Returns project info and server mode. Do not use for error details — use vf_get_errors instead.",
|
|
77
86
|
inputSchema: getDebugContextInput,
|
|
78
87
|
execute: (input) =>
|
|
79
88
|
withSpan(
|
|
@@ -114,7 +123,7 @@ export const vfGetDebugContext: MCPTool<GetDebugContextInput, DebugContextResult
|
|
|
114
123
|
// ============================================================================
|
|
115
124
|
|
|
116
125
|
const triggerHmrInput = z.object({
|
|
117
|
-
path: z.string().describe("File path that changed
|
|
126
|
+
path: z.string().describe("File path that changed. Example: 'app/page.tsx'."),
|
|
118
127
|
port: z.number().int().min(1).max(65535).optional().default(8080).describe(
|
|
119
128
|
"Dev server port (defaults to 8080)",
|
|
120
129
|
),
|
|
@@ -129,8 +138,15 @@ interface TriggerHmrResult {
|
|
|
129
138
|
|
|
130
139
|
export const vfTriggerHmr: MCPTool<TriggerHmrInput, TriggerHmrResult> = {
|
|
131
140
|
name: "vf_trigger_hmr",
|
|
141
|
+
title: "Trigger HMR",
|
|
142
|
+
annotations: {
|
|
143
|
+
readOnlyHint: false,
|
|
144
|
+
destructiveHint: false,
|
|
145
|
+
idempotentHint: true,
|
|
146
|
+
openWorldHint: false,
|
|
147
|
+
},
|
|
132
148
|
description:
|
|
133
|
-
"
|
|
149
|
+
"Use this when you need to force an HMR update for a specific file path. Sends a WebSocket reload notification to connected browsers. Returns success status and active listener count. Do not use if no browser is connected — check vf_get_flywheel_status first.",
|
|
134
150
|
inputSchema: triggerHmrInput,
|
|
135
151
|
execute: (input) => {
|
|
136
152
|
const metrics = ReloadNotifier.getMetrics();
|
|
@@ -156,7 +172,7 @@ export const vfTriggerHmr: MCPTool<TriggerHmrInput, TriggerHmrResult> = {
|
|
|
156
172
|
|
|
157
173
|
const previewRouteInput = z.object({
|
|
158
174
|
route: z.string().startsWith("/", "Route must start with /").describe(
|
|
159
|
-
"Route path to preview
|
|
175
|
+
"Route path to preview. Example: '/', '/dashboard', '/api/users'.",
|
|
160
176
|
),
|
|
161
177
|
port: z.number().int().min(1).max(65535).optional().default(8080).describe(
|
|
162
178
|
"Dev server port (defaults to 8080)",
|
|
@@ -165,7 +181,9 @@ const previewRouteInput = z.object({
|
|
|
165
181
|
.enum(["html", "json", "status"])
|
|
166
182
|
.optional()
|
|
167
183
|
.default("status")
|
|
168
|
-
.describe(
|
|
184
|
+
.describe(
|
|
185
|
+
"Output format: 'html' for full page, 'json' for API response, 'status' for just HTTP status. Defaults to 'status'.",
|
|
186
|
+
),
|
|
169
187
|
});
|
|
170
188
|
|
|
171
189
|
type PreviewRouteInput = z.infer<typeof previewRouteInput>;
|
|
@@ -182,8 +200,10 @@ interface PreviewRouteResult {
|
|
|
182
200
|
|
|
183
201
|
export const vfPreviewRoute: MCPTool<PreviewRouteInput, PreviewRouteResult> = {
|
|
184
202
|
name: "vf_preview_route",
|
|
203
|
+
title: "Preview Route",
|
|
204
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
185
205
|
description:
|
|
186
|
-
"
|
|
206
|
+
"Use this when you need to test-render a route and inspect the response. Returns rendered output, HTTP status, and render time. Note: API routes may have side effects. Do not use for listing routes — use vf_list_routes instead.",
|
|
187
207
|
inputSchema: previewRouteInput,
|
|
188
208
|
execute: (input) =>
|
|
189
209
|
withSpan(
|
|
@@ -263,8 +283,10 @@ interface WaitForReadyResult {
|
|
|
263
283
|
|
|
264
284
|
export const vfWaitForReady: MCPTool<WaitForReadyInput, WaitForReadyResult> = {
|
|
265
285
|
name: "vf_wait_for_ready",
|
|
286
|
+
title: "Wait for Ready",
|
|
287
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
266
288
|
description:
|
|
267
|
-
"
|
|
289
|
+
"Use this when you need to wait for the dev server to become ready after restart. Polls the health endpoint until responsive. Returns success status and elapsed time. Do not use for error counts or uptime — use vf_get_status instead.",
|
|
268
290
|
inputSchema: waitForReadyInput,
|
|
269
291
|
execute: (input) =>
|
|
270
292
|
withSpan(
|
|
@@ -351,8 +373,10 @@ interface FlywheelStatus {
|
|
|
351
373
|
|
|
352
374
|
export const vfGetFlywheelStatus: MCPTool<GetFlywheelStatusInput, FlywheelStatus> = {
|
|
353
375
|
name: "vf_get_flywheel_status",
|
|
376
|
+
title: "Flywheel Status",
|
|
377
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
354
378
|
description:
|
|
355
|
-
"
|
|
379
|
+
"Use this when you need a comprehensive status overview combining server health, error counts, and HMR statistics. Returns server status, error/log counts, and HMR metrics in one response. Do not use for detailed error or log content — use vf_get_errors or vf_get_logs instead.",
|
|
356
380
|
inputSchema: getFlywheelStatusInput,
|
|
357
381
|
execute: (input) =>
|
|
358
382
|
withSpan(
|
|
@@ -11,8 +11,10 @@ const getSchemaInput = z.object({
|
|
|
11
11
|
|
|
12
12
|
const vfGetSchema: MCPTool = {
|
|
13
13
|
name: "vf_get_schema",
|
|
14
|
+
title: "Get CLI Schema",
|
|
15
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
14
16
|
description:
|
|
15
|
-
"
|
|
17
|
+
"Use this when you need to discover available CLI commands, their arguments, and flags. Returns the command schema as JSON. Do not use for project info — use vf_get_project_info instead.",
|
|
16
18
|
inputSchema: getSchemaInput,
|
|
17
19
|
execute: async (input: { command?: string; category?: string }) => {
|
|
18
20
|
if (input.command) {
|
|
@@ -26,7 +28,10 @@ const getProjectInfoInput = z.object({});
|
|
|
26
28
|
|
|
27
29
|
const vfGetProjectInfo: MCPTool = {
|
|
28
30
|
name: "vf_get_project_info",
|
|
29
|
-
|
|
31
|
+
title: "Get Project Info",
|
|
32
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
33
|
+
description:
|
|
34
|
+
"Use this when you need project metadata including project slug, version, and environment. Returns slug, version, and environment config. Do not use for CLI commands — use vf_get_schema instead.",
|
|
30
35
|
inputSchema: getProjectInfoInput,
|
|
31
36
|
execute: async () => {
|
|
32
37
|
const { getEnvironmentConfig } = await import("../../../src/config/index.js");
|
|
@@ -37,8 +37,10 @@ type ListRoutesInput = z.infer<typeof listRoutesInput>;
|
|
|
37
37
|
|
|
38
38
|
export const vfListRoutes: MCPTool<ListRoutesInput, RouteInfo[]> = {
|
|
39
39
|
name: "vf_list_routes",
|
|
40
|
+
title: "List Routes",
|
|
41
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
40
42
|
description:
|
|
41
|
-
"
|
|
43
|
+
"Use this when you need to discover all routes in the project including pages, API routes, layouts, error, loading, and not-found routes. Returns an array of route info with path, type, and file. Do not use for rendering a route — use vf_preview_route instead.",
|
|
42
44
|
inputSchema: listRoutesInput,
|
|
43
45
|
execute: (input) =>
|
|
44
46
|
withSpan(
|
|
@@ -142,8 +144,10 @@ async function getProjectName(projectDir: string, fs: FileSystem): Promise<strin
|
|
|
142
144
|
|
|
143
145
|
export const vfGetProjectContext: MCPTool<GetProjectContextInput, ProjectContext> = {
|
|
144
146
|
name: "vf_get_project_context",
|
|
147
|
+
title: "Project Context",
|
|
148
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
145
149
|
description:
|
|
146
|
-
"
|
|
150
|
+
"Use this when you need to understand the project structure, conventions, and capabilities at the start of a coding session. Also returns route information. Do not use for detailed per-route rendering — use vf_preview_route instead.",
|
|
147
151
|
inputSchema: getProjectContextInput,
|
|
148
152
|
execute: (input) =>
|
|
149
153
|
withSpan(
|
|
@@ -219,8 +223,10 @@ function toRelativePath(absolutePath: string, projectDir: string): string {
|
|
|
219
223
|
|
|
220
224
|
export const vfGetComponentTree: MCPTool<GetComponentTreeInput, ComponentTreeResult> = {
|
|
221
225
|
name: "vf_get_component_tree",
|
|
226
|
+
title: "Component Tree",
|
|
227
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
222
228
|
description:
|
|
223
|
-
"
|
|
229
|
+
"Use this when you need to analyze the component hierarchy for a specific route including layouts, providers, and nested components. Returns the component tree structure. Do not use for listing all routes — use vf_list_routes instead.",
|
|
224
230
|
inputSchema: getComponentTreeInput,
|
|
225
231
|
execute: (input) =>
|
|
226
232
|
withSpan(
|
|
@@ -375,8 +381,10 @@ async function scanForProjects(
|
|
|
375
381
|
|
|
376
382
|
export const vfListLocalProjects: MCPTool<ListLocalProjectsInput, LocalProjectInfo[]> = {
|
|
377
383
|
name: "vf_list_local_projects",
|
|
384
|
+
title: "List Local Projects",
|
|
385
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
378
386
|
description:
|
|
379
|
-
"
|
|
387
|
+
"Use this when you need to discover Veryfront projects on the local filesystem by scanning for veryfront.config.ts files. Returns project info including template type and integrations. Do not use for project structure details — use vf_get_project_context instead.",
|
|
380
388
|
inputSchema: listLocalProjectsInput,
|
|
381
389
|
execute: (input) =>
|
|
382
390
|
withSpan(
|
|
@@ -209,8 +209,10 @@ const SCAFFOLD_CONFIGS: Record<ScaffoldType, ScaffoldConfig> = {
|
|
|
209
209
|
|
|
210
210
|
export const vfScaffold: MCPTool<ScaffoldInput, ScaffoldResult> = {
|
|
211
211
|
name: "vf_scaffold",
|
|
212
|
+
title: "Scaffold Code",
|
|
213
|
+
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false },
|
|
212
214
|
description:
|
|
213
|
-
"
|
|
215
|
+
"Use this when you need to generate new pages, API routes, layouts, components, AI tools, agents, or prompts with proper Veryfront conventions. Returns the created file path and content. May overwrite existing files at the target path. Do not use for creating entire projects — use vf_create_project instead.",
|
|
214
216
|
inputSchema: scaffoldInput,
|
|
215
217
|
execute: (input) =>
|
|
216
218
|
withSpan(
|
|
@@ -400,8 +402,10 @@ const CONVENTIONS: Record<string, Convention> = {
|
|
|
400
402
|
|
|
401
403
|
export const vfGetConventions: MCPTool<GetConventionsInput, Convention[]> = {
|
|
402
404
|
name: "vf_get_conventions",
|
|
405
|
+
title: "Get Conventions",
|
|
406
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
403
407
|
description:
|
|
404
|
-
"
|
|
408
|
+
"Use this when you need Veryfront coding conventions and best practices for routing, API, components, AI, or styling. Do not use for project structure — use vf_get_project_context instead.",
|
|
405
409
|
inputSchema: getConventionsInput,
|
|
406
410
|
execute: (input) => {
|
|
407
411
|
if (input.topic === "all") return Promise.resolve(Object.values(CONVENTIONS));
|
|
@@ -91,8 +91,10 @@ interface GetSkillsResult {
|
|
|
91
91
|
|
|
92
92
|
export const vfGetSkills: MCPTool<GetSkillsInput, GetSkillsResult> = {
|
|
93
93
|
name: "vf_get_skills",
|
|
94
|
+
title: "Get Skills",
|
|
95
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
94
96
|
description:
|
|
95
|
-
"
|
|
97
|
+
"Use this when you need to discover available Agent Skills or load a specific skill's procedural knowledge. Returns skill names and descriptions, or full skill content when name is provided. Do not use for skill reference docs — use vf_get_skill_reference instead.",
|
|
96
98
|
inputSchema: getSkillsInput,
|
|
97
99
|
execute: (input) =>
|
|
98
100
|
withSpan(
|
|
@@ -168,8 +170,10 @@ interface GetSkillReferenceResult {
|
|
|
168
170
|
|
|
169
171
|
export const vfGetSkillReference: MCPTool<GetSkillReferenceInput, GetSkillReferenceResult> = {
|
|
170
172
|
name: "vf_get_skill_reference",
|
|
173
|
+
title: "Get Skill Reference",
|
|
174
|
+
annotations: { readOnlyHint: true, idempotentHint: true, openWorldHint: false },
|
|
171
175
|
description:
|
|
172
|
-
"
|
|
176
|
+
"Use this when you need to load a specific reference document from a skill. Returns the document content as text. Do not use for skill discovery — use vf_get_skills instead.",
|
|
173
177
|
inputSchema: getSkillReferenceInput,
|
|
174
178
|
execute: async (input) => {
|
|
175
179
|
const fs = getFs();
|