veryfront 0.1.146 → 0.1.148

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.
Files changed (42) hide show
  1. package/esm/deno.js +3 -9
  2. package/esm/src/internal-agents/run-stream.d.ts.map +1 -1
  3. package/esm/src/internal-agents/run-stream.js +60 -79
  4. package/esm/src/internal-agents/schema.d.ts +243 -4
  5. package/esm/src/internal-agents/schema.d.ts.map +1 -1
  6. package/esm/src/internal-agents/schema.js +219 -8
  7. package/esm/src/jobs/schemas.d.ts +4 -4
  8. package/esm/src/mcp/elicitation.d.ts +16 -0
  9. package/esm/src/mcp/elicitation.d.ts.map +1 -0
  10. package/esm/src/mcp/elicitation.js +21 -0
  11. package/esm/src/mcp/index.d.ts +3 -0
  12. package/esm/src/mcp/index.d.ts.map +1 -1
  13. package/esm/src/mcp/index.js +2 -0
  14. package/esm/src/mcp/server.d.ts +22 -0
  15. package/esm/src/mcp/server.d.ts.map +1 -1
  16. package/esm/src/mcp/server.js +163 -2
  17. package/esm/src/mcp/task-store.d.ts +27 -0
  18. package/esm/src/mcp/task-store.d.ts.map +1 -0
  19. package/esm/src/mcp/task-store.js +116 -0
  20. package/esm/src/modules/react-loader/ssr-module-loader/cache/memory.d.ts.map +1 -1
  21. package/esm/src/modules/react-loader/ssr-module-loader/cache/memory.js +4 -2
  22. package/esm/src/server/handlers/request/agent-stream.handler.d.ts.map +1 -1
  23. package/esm/src/server/handlers/request/agent-stream.handler.js +4 -3
  24. package/esm/src/tool/remote-mcp.d.ts.map +1 -1
  25. package/esm/src/tool/remote-mcp.js +60 -1
  26. package/esm/src/tool/types.d.ts +2 -0
  27. package/esm/src/tool/types.d.ts.map +1 -1
  28. package/esm/src/utils/version-constant.d.ts +1 -1
  29. package/esm/src/utils/version-constant.js +1 -1
  30. package/package.json +1 -1
  31. package/src/deno.js +3 -9
  32. package/src/src/internal-agents/run-stream.ts +61 -94
  33. package/src/src/internal-agents/schema.ts +277 -10
  34. package/src/src/mcp/elicitation.ts +42 -0
  35. package/src/src/mcp/index.ts +9 -0
  36. package/src/src/mcp/server.ts +185 -2
  37. package/src/src/mcp/task-store.ts +137 -0
  38. package/src/src/modules/react-loader/ssr-module-loader/cache/memory.ts +4 -2
  39. package/src/src/server/handlers/request/agent-stream.handler.ts +5 -3
  40. package/src/src/tool/remote-mcp.ts +86 -1
  41. package/src/src/tool/types.ts +2 -0
  42. package/src/src/utils/version-constant.ts +1 -1
@@ -61,22 +61,233 @@ export const RuntimeAgentSourceContextSchema = z.discriminatedUnion("type", [
61
61
  releaseId: z.string().min(1).max(255),
62
62
  }),
63
63
  ]);
64
+ const RuntimeMessageExtensionFieldsSchema = {
65
+ name: z.string().max(256).optional(),
66
+ metadata: z.record(z.string(), z.unknown()).optional(),
67
+ createdAt: z.string().optional(),
68
+ };
69
+ export const RuntimeToolFunctionCallSchema = z.object({
70
+ name: ClientToolNameSchema,
71
+ arguments: z.string().max(MAX_TOOL_PARAMETERS_BYTES),
72
+ }).strict();
73
+ export const RuntimeToolCallSchema = z.object({
74
+ id: z.string().min(1).max(128),
75
+ type: z.literal("function"),
76
+ function: RuntimeToolFunctionCallSchema,
77
+ }).strict();
78
+ export const RuntimeSystemMessageSchema = z.object({
79
+ id: z.string().min(1),
80
+ role: z.literal("system"),
81
+ content: z.string(),
82
+ ...RuntimeMessageExtensionFieldsSchema,
83
+ }).strict();
84
+ export const RuntimeUserMessageSchema = z.object({
85
+ id: z.string().min(1),
86
+ role: z.literal("user"),
87
+ content: z.string(),
88
+ ...RuntimeMessageExtensionFieldsSchema,
89
+ }).strict();
90
+ export const RuntimeAssistantMessageSchema = z.object({
91
+ id: z.string().min(1),
92
+ role: z.literal("assistant"),
93
+ content: z.string().optional(),
94
+ toolCalls: z.array(RuntimeToolCallSchema).optional(),
95
+ ...RuntimeMessageExtensionFieldsSchema,
96
+ }).strict();
97
+ export const RuntimeToolMessageSchema = z.object({
98
+ id: z.string().min(1),
99
+ role: z.literal("tool"),
100
+ toolCallId: z.string().min(1).max(128),
101
+ content: z.string(),
102
+ error: z.string().optional(),
103
+ ...RuntimeMessageExtensionFieldsSchema,
104
+ }).strict();
105
+ export const RuntimeMessageSchema = z.discriminatedUnion("role", [
106
+ RuntimeSystemMessageSchema,
107
+ RuntimeUserMessageSchema,
108
+ RuntimeAssistantMessageSchema,
109
+ RuntimeToolMessageSchema,
110
+ ]);
111
+ export const RuntimeContextSchema = z.union([
112
+ z.object({
113
+ description: z.string().max(1024),
114
+ value: z.string().max(MAX_CONTEXT_ITEM_BYTES),
115
+ }),
116
+ RuntimeContextItemSchema,
117
+ ]);
64
118
  export const RuntimeRunAgentInputSchema = z.object({
119
+ threadId: z.string().uuid(),
120
+ runId: RunIdSchema,
121
+ parentRunId: RunIdSchema.optional(),
122
+ state: z.unknown().optional(),
123
+ messages: z.array(RuntimeMessageSchema).max(MAX_RUNTIME_MESSAGES),
124
+ tools: z.array(RuntimeInjectedToolSchema).max(50).default([]),
125
+ context: z.array(RuntimeContextSchema).max(10).default([]).refine((value) => isWithinJsonSizeLimit(value, MAX_CONTEXT_TOTAL_BYTES), { message: "context must be less than 64 KB total" }),
126
+ forwardedProps: z.record(z.string(), z.unknown()).optional().refine((value) => value === undefined || isWithinJsonSizeLimit(value, MAX_FORWARDED_PROPS_BYTES), { message: "forwardedProps must be less than 64 KB" }),
127
+ });
128
+ export const InternalAgentCompatibilityMessageSchema = z.object({
129
+ id: z.string().min(1),
130
+ role: z.enum(["user", "assistant", "system", "tool"]),
131
+ parts: z.array(z.object({ type: z.string().min(1) }).passthrough()).default([]),
132
+ metadata: z.record(z.string(), z.unknown()).optional(),
133
+ createdAt: z.string().optional(),
134
+ });
135
+ export const InternalAgentStreamRequestSchema = z.object({
65
136
  agentId: AgentIdSchema,
66
137
  threadId: z.string().uuid(),
67
138
  runId: RunIdSchema,
68
- messages: z.array(z.object({
69
- id: z.string().min(1),
70
- role: z.enum(["user", "assistant", "system", "tool"]),
71
- parts: z.array(z.object({ type: z.string().min(1) }).passthrough()).default([]),
72
- metadata: z.record(z.string(), z.unknown()).optional(),
73
- createdAt: z.string().optional(),
74
- })).max(MAX_RUNTIME_MESSAGES),
139
+ parentRunId: RunIdSchema.optional(),
140
+ state: z.unknown().optional(),
141
+ messages: z.array(z.union([RuntimeMessageSchema, InternalAgentCompatibilityMessageSchema])).max(MAX_RUNTIME_MESSAGES),
75
142
  tools: z.array(RuntimeInjectedToolSchema).max(50).default([]),
76
- context: z.array(RuntimeContextItemSchema).max(10).default([]).refine((value) => isWithinJsonSizeLimit(value, MAX_CONTEXT_TOTAL_BYTES), { message: "context must be less than 64 KB total" }),
143
+ context: z.array(RuntimeContextSchema).max(10).default([]).refine((value) => isWithinJsonSizeLimit(value, MAX_CONTEXT_TOTAL_BYTES), { message: "context must be less than 64 KB total" }),
77
144
  agentSource: RuntimeAgentSourceContextSchema.optional(),
78
145
  forwardedProps: z.record(z.string(), z.unknown()).optional().refine((value) => value === undefined || isWithinJsonSizeLimit(value, MAX_FORWARDED_PROPS_BYTES), { message: "forwardedProps must be less than 64 KB" }),
79
146
  });
147
+ function extractToolArgs(part) {
148
+ const args = part.args;
149
+ if (args && typeof args === "object" && !Array.isArray(args)) {
150
+ return args;
151
+ }
152
+ const input = part.input;
153
+ if (input && typeof input === "object" && !Array.isArray(input)) {
154
+ return input;
155
+ }
156
+ return {};
157
+ }
158
+ function serializeToolArguments(args) {
159
+ try {
160
+ return JSON.stringify(args);
161
+ }
162
+ catch {
163
+ return "{}";
164
+ }
165
+ }
166
+ function getPartString(part, ...keys) {
167
+ for (const key of keys) {
168
+ const value = part[key];
169
+ if (typeof value === "string" && value.length > 0) {
170
+ return value;
171
+ }
172
+ }
173
+ return null;
174
+ }
175
+ function isLegacyToolCallPart(part) {
176
+ return getPartString(part, "type") === "tool_call";
177
+ }
178
+ function isCanonicalToolCallPart(part) {
179
+ const type = getPartString(part, "type");
180
+ return type === "tool-call" ||
181
+ (typeof type === "string" && type.startsWith("tool-") && type !== "tool-result" &&
182
+ type !== "tool_result");
183
+ }
184
+ function getToolCallShape(part) {
185
+ const id = getPartString(part, "toolCallId", "tool_call_id", "id");
186
+ const name = getPartString(part, "toolName", "tool_name", "name");
187
+ if (!id || !name) {
188
+ return null;
189
+ }
190
+ return {
191
+ id,
192
+ type: "function",
193
+ function: {
194
+ name,
195
+ arguments: serializeToolArguments(extractToolArgs(part)),
196
+ },
197
+ };
198
+ }
199
+ function isToolResultPart(part) {
200
+ const type = getPartString(part, "type");
201
+ return type === "tool-result" || type === "tool_result";
202
+ }
203
+ function stringifyToolResult(result) {
204
+ if (typeof result === "string") {
205
+ return result;
206
+ }
207
+ try {
208
+ return JSON.stringify(result);
209
+ }
210
+ catch {
211
+ return String(result);
212
+ }
213
+ }
214
+ function toRuntimeMessage(message) {
215
+ if (!("parts" in message)) {
216
+ return message;
217
+ }
218
+ const textContent = message.parts
219
+ .filter((part) => part.type === "text" && typeof part.text === "string")
220
+ .map((part) => part.text)
221
+ .join("\n");
222
+ const sharedFields = {
223
+ ...(message.metadata ? { metadata: message.metadata } : {}),
224
+ ...(message.createdAt ? { createdAt: message.createdAt } : {}),
225
+ };
226
+ switch (message.role) {
227
+ case "system":
228
+ return {
229
+ id: message.id,
230
+ role: "system",
231
+ content: textContent,
232
+ ...sharedFields,
233
+ };
234
+ case "user":
235
+ return {
236
+ id: message.id,
237
+ role: "user",
238
+ content: textContent,
239
+ ...sharedFields,
240
+ };
241
+ case "assistant": {
242
+ const toolCalls = message.parts.flatMap((part) => {
243
+ if (!isCanonicalToolCallPart(part) && !isLegacyToolCallPart(part)) {
244
+ return [];
245
+ }
246
+ const toolCall = getToolCallShape(part);
247
+ return toolCall ? [toolCall] : [];
248
+ });
249
+ return {
250
+ id: message.id,
251
+ role: "assistant",
252
+ ...(textContent ? { content: textContent } : {}),
253
+ ...(toolCalls.length ? { toolCalls } : {}),
254
+ ...sharedFields,
255
+ };
256
+ }
257
+ case "tool": {
258
+ const toolResultPart = message.parts.find((part) => isToolResultPart(part) && getPartString(part, "toolCallId", "tool_call_id") !== null);
259
+ const toolCallId = toolResultPart
260
+ ? getPartString(toolResultPart, "toolCallId", "tool_call_id")
261
+ : null;
262
+ const toolResult = toolResultPart && "result" in toolResultPart
263
+ ? toolResultPart.result
264
+ : toolResultPart && "output" in toolResultPart
265
+ ? toolResultPart.output
266
+ : undefined;
267
+ const toolError = toolResultPart ? getPartString(toolResultPart, "error") : null;
268
+ return {
269
+ id: message.id,
270
+ role: "tool",
271
+ toolCallId: toolCallId ?? message.id,
272
+ content: toolResult !== undefined ? stringifyToolResult(toolResult) : textContent,
273
+ ...(toolError ? { error: toolError } : {}),
274
+ ...sharedFields,
275
+ };
276
+ }
277
+ }
278
+ }
279
+ export function toRuntimeRunAgentInput(input) {
280
+ return {
281
+ threadId: input.threadId,
282
+ runId: input.runId,
283
+ ...(input.parentRunId ? { parentRunId: input.parentRunId } : {}),
284
+ ...(input.state !== undefined ? { state: input.state } : {}),
285
+ messages: input.messages.map(toRuntimeMessage),
286
+ tools: input.tools,
287
+ context: input.context,
288
+ ...(input.forwardedProps ? { forwardedProps: input.forwardedProps } : {}),
289
+ };
290
+ }
80
291
  export const ResumeSignalSchema = z.discriminatedUnion("type", [
81
292
  z.object({
82
293
  type: z.literal("tool_result"),
@@ -2,9 +2,9 @@ import { z } from "zod";
2
2
  export declare const JobStatusSchema: z.ZodEnum<{
3
3
  failed: "failed";
4
4
  completed: "completed";
5
+ working: "working";
5
6
  canceled: "canceled";
6
7
  submitted: "submitted";
7
- working: "working";
8
8
  }>;
9
9
  export declare const CronJobStatusSchema: z.ZodEnum<{
10
10
  deleting: "deleting";
@@ -199,9 +199,9 @@ export declare const JobSchema: z.ZodObject<{
199
199
  status: z.ZodEnum<{
200
200
  failed: "failed";
201
201
  completed: "completed";
202
+ working: "working";
202
203
  canceled: "canceled";
203
204
  submitted: "submitted";
204
- working: "working";
205
205
  }>;
206
206
  target: z.ZodString;
207
207
  config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -302,9 +302,9 @@ export declare const JobListItemSchema: z.ZodObject<{
302
302
  status: z.ZodEnum<{
303
303
  failed: "failed";
304
304
  completed: "completed";
305
+ working: "working";
305
306
  canceled: "canceled";
306
307
  submitted: "submitted";
307
- working: "working";
308
308
  }>;
309
309
  target: z.ZodString;
310
310
  config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -351,9 +351,9 @@ export declare const PaginatedJobsResponseSchema: z.ZodObject<{
351
351
  status: z.ZodEnum<{
352
352
  failed: "failed";
353
353
  completed: "completed";
354
+ working: "working";
354
355
  canceled: "canceled";
355
356
  submitted: "submitted";
356
- working: "working";
357
357
  }>;
358
358
  target: z.ZodString;
359
359
  config: z.ZodRecord<z.ZodString, z.ZodUnknown>;
@@ -0,0 +1,16 @@
1
+ export interface FormElicitationOptions {
2
+ message: string;
3
+ schema: Record<string, unknown>;
4
+ }
5
+ export interface UrlElicitationOptions {
6
+ message: string;
7
+ url: string;
8
+ elicitationId: string;
9
+ }
10
+ export interface ElicitationRequest {
11
+ method: "elicitation/create";
12
+ params: Record<string, unknown>;
13
+ }
14
+ export declare function buildFormElicitation(options: FormElicitationOptions): ElicitationRequest;
15
+ export declare function buildUrlElicitation(options: UrlElicitationOptions): ElicitationRequest;
16
+ //# sourceMappingURL=elicitation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"elicitation.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/elicitation.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,sBAAsB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,oBAAoB,CAAC;IAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACjC;AAED,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,sBAAsB,GAC9B,kBAAkB,CASpB;AAED,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,qBAAqB,GAC7B,kBAAkB,CAUpB"}
@@ -0,0 +1,21 @@
1
+ export function buildFormElicitation(options) {
2
+ return {
3
+ method: "elicitation/create",
4
+ params: {
5
+ mode: "form",
6
+ message: options.message,
7
+ requestedSchema: options.schema,
8
+ },
9
+ };
10
+ }
11
+ export function buildUrlElicitation(options) {
12
+ return {
13
+ method: "elicitation/create",
14
+ params: {
15
+ mode: "url",
16
+ message: options.message,
17
+ url: options.url,
18
+ elicitationId: options.elicitationId,
19
+ },
20
+ };
21
+ }
@@ -25,6 +25,9 @@ import "../../_dnt.polyfills.js";
25
25
  export type { MCPServerConfig, MCPStats, MCPTool, ToolAnnotations, ToolListEntry, } from "./types.js";
26
26
  export { clearMCPRegistry, getMCPRegistry, getMCPStats, registerPrompt, registerResource, registerTool, } from "./registry.js";
27
27
  export { createMCPServer, type IntegrationLoaderConfig, MCPServer } from "./server.js";
28
+ export { buildFormElicitation, buildUrlElicitation, type ElicitationRequest, type FormElicitationOptions, type UrlElicitationOptions, } from "./elicitation.js";
28
29
  export { formatSSEEvent, formatSSEPrimingEvent, formatSSERetry } from "./sse.js";
29
30
  export { SessionManager } from "./session.js";
31
+ export { TaskStore } from "./task-store.js";
32
+ export type { Task } from "./task-store.js";
30
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,eAAe,EACf,QAAQ,EACR,OAAO,EACP,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,KAAK,uBAAuB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,yBAAyB,CAAC;AAGjC,YAAY,EACV,eAAe,EACf,QAAQ,EACR,OAAO,EACP,eAAe,EACf,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,WAAW,EACX,cAAc,EACd,gBAAgB,EAChB,YAAY,GACb,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,eAAe,EAAE,KAAK,uBAAuB,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAEvF,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,YAAY,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC"}
@@ -24,5 +24,7 @@
24
24
  import "../../_dnt.polyfills.js";
25
25
  export { clearMCPRegistry, getMCPRegistry, getMCPStats, registerPrompt, registerResource, registerTool, } from "./registry.js";
26
26
  export { createMCPServer, MCPServer } from "./server.js";
27
+ export { buildFormElicitation, buildUrlElicitation, } from "./elicitation.js";
27
28
  export { formatSSEEvent, formatSSEPrimingEvent, formatSSERetry } from "./sse.js";
28
29
  export { SessionManager } from "./session.js";
30
+ export { TaskStore } from "./task-store.js";
@@ -25,11 +25,25 @@ export interface IntegrationLoaderConfig {
25
25
  apiToken?: string;
26
26
  }
27
27
  export declare class MCPServer {
28
+ private static LOG_LEVELS;
29
+ private logLevel;
28
30
  private config;
29
31
  private integrationLoader?;
30
32
  private integrationsLoaded;
31
33
  private sessionManager;
34
+ private taskStore;
35
+ private pendingTasks;
36
+ private clientCapabilities;
37
+ /** Callback for server-initiated notifications. Set by transport layer. */
38
+ onNotification?: (notification: {
39
+ jsonrpc: "2.0";
40
+ method: string;
41
+ params?: unknown;
42
+ }) => void;
32
43
  constructor(config: MCPServerConfig);
44
+ notifyToolsChanged(): void;
45
+ notifyResourcesChanged(): void;
46
+ notifyPromptsChanged(): void;
33
47
  /**
34
48
  * Configure integration tools to be loaded from the API.
35
49
  *
@@ -38,6 +52,7 @@ export declare class MCPServer {
38
52
  * Otherwise falls back to the legacy local loading path.
39
53
  */
40
54
  setIntegrationLoader(config: IntegrationLoaderConfig): void;
55
+ clientSupportsElicitation(mode: "form" | "url"): boolean;
41
56
  handleRequest(request: JSONRPCRequest, context?: ToolExecutionContext): Promise<JSONRPCResponse>;
42
57
  private dispatch;
43
58
  private initialize;
@@ -49,6 +64,13 @@ export declare class MCPServer {
49
64
  private listPrompts;
50
65
  private getPrompt;
51
66
  private complete;
67
+ private setLogLevel;
68
+ private getTask;
69
+ private getTaskResult;
70
+ private cancelTask;
71
+ private listTasks;
72
+ /** Wait for all background task executions to settle. Useful in tests. */
73
+ waitForPendingTasks(): Promise<void>;
52
74
  createHTTPHandler(): (request: dntShim.Request) => Promise<dntShim.Response>;
53
75
  private extractRequestContext;
54
76
  private validateAuth;
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,qBAAqB,CAAC;AAG/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAI7D,OAAO,KAAK,EAAE,eAAe,EAAiB,MAAM,YAAY,CAAC;AAMjE,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAYzE,KAAK,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,CAAC;AA4DzD,UAAU,cAAc;IACtB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,UAAU,eAAe;IACvB,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,CAAC;CACH;AAED,MAAM,WAAW,uBAAuB;IACtC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,wBAAwB,GAAG,SAAS,CAAC,CAAC;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAID,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,iBAAiB,CAAC,CAA0B;IACpD,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,cAAc,CAAwB;gBAElC,MAAM,EAAE,eAAe;IAQnC;;;;;;OAMG;IACH,oBAAoB,CAAC,MAAM,EAAE,uBAAuB,GAAG,IAAI;IAK3D,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAC,eAAe,CAAC;IAmBhG,OAAO,CAAC,QAAQ;IAoChB,OAAO,CAAC,UAAU;YA2BJ,SAAS;IA6BvB,OAAO,CAAC,QAAQ;IAgDhB,OAAO,CAAC,qBAAqB;IAuB7B,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,YAAY;IA6CpB,OAAO,CAAC,WAAW;IAgBnB,OAAO,CAAC,SAAS;IAuCjB,OAAO,CAAC,QAAQ;IAUhB,iBAAiB,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC;IAiG5E,OAAO,CAAC,qBAAqB;YAgBf,YAAY;IAsB1B,OAAO,CAAC,cAAc;YAsBR,0BAA0B;CAqBzC;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAElE"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/src/mcp/server.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,7 @@ import { validateContentType } from "../security/input-validation/limits.js";
11
11
  import { VeryfrontError } from "../security/input-validation/errors.js";
12
12
  import { logger as baseLogger } from "../utils/index.js";
13
13
  import { SessionManager } from "./session.js";
14
+ import { TaskStore } from "./task-store.js";
14
15
  const logger = baseLogger.component("mcp-server");
15
16
  const MAX_REQUEST_BODY_SIZE = 1_048_576; // 1 MB
16
17
  const MAX_CONTEXT_HEADER_LENGTH = 255;
@@ -66,16 +67,43 @@ function readAllowedHeader(request, headerName, pattern) {
66
67
  }
67
68
  const MCP_SUPPORTED_VERSIONS = ["2025-11-25", "2024-11-05"];
68
69
  export class MCPServer {
70
+ static LOG_LEVELS = [
71
+ "debug",
72
+ "info",
73
+ "notice",
74
+ "warning",
75
+ "error",
76
+ "critical",
77
+ "alert",
78
+ "emergency",
79
+ ];
80
+ logLevel = "warning";
69
81
  config;
70
82
  integrationLoader;
71
83
  integrationsLoaded = false;
72
84
  sessionManager = new SessionManager();
85
+ taskStore = new TaskStore();
86
+ pendingTasks = new Map();
87
+ // TODO(#842): capabilities should be stored per-session (keyed by MCP-Session-Id)
88
+ // so concurrent clients don't overwrite each other's capability flags.
89
+ clientCapabilities = {};
90
+ /** Callback for server-initiated notifications. Set by transport layer. */
91
+ onNotification;
73
92
  constructor(config) {
74
93
  this.config = config;
75
94
  if (!config.auth || config.auth.type === "none") {
76
95
  logger.warn("MCP server has no authentication configured — all requests will be accepted");
77
96
  }
78
97
  }
98
+ notifyToolsChanged() {
99
+ this.onNotification?.({ jsonrpc: "2.0", method: "notifications/tools/list_changed" });
100
+ }
101
+ notifyResourcesChanged() {
102
+ this.onNotification?.({ jsonrpc: "2.0", method: "notifications/resources/list_changed" });
103
+ }
104
+ notifyPromptsChanged() {
105
+ this.onNotification?.({ jsonrpc: "2.0", method: "notifications/prompts/list_changed" });
106
+ }
79
107
  /**
80
108
  * Configure integration tools to be loaded from the API.
81
109
  *
@@ -87,6 +115,16 @@ export class MCPServer {
87
115
  this.integrationLoader = config;
88
116
  this.integrationsLoaded = false;
89
117
  }
118
+ clientSupportsElicitation(mode) {
119
+ const raw = this.clientCapabilities.elicitation;
120
+ if (!raw || typeof raw !== "object" || Array.isArray(raw))
121
+ return false;
122
+ const elicitation = raw;
123
+ // Per MCP spec: empty elicitation object implies basic form support (backwards compat)
124
+ if (mode === "form" && Object.keys(elicitation).length === 0)
125
+ return true;
126
+ return mode in elicitation;
127
+ }
90
128
  handleRequest(request, context) {
91
129
  return withSpan("mcp.handleRequest", async () => {
92
130
  try {
@@ -122,8 +160,21 @@ export class MCPServer {
122
160
  return this.initialize(params);
123
161
  case "notifications/initialized":
124
162
  return Promise.resolve({});
163
+ case "notifications/cancelled":
164
+ // TODO(#841): propagate cancellation to in-flight tool executions via AbortController
165
+ return Promise.resolve({});
125
166
  case "completion/complete":
126
167
  return this.complete(params);
168
+ case "logging/setLevel":
169
+ return this.setLogLevel(params);
170
+ case "tasks/get":
171
+ return this.getTask(params);
172
+ case "tasks/result":
173
+ return this.getTaskResult(params);
174
+ case "tasks/cancel":
175
+ return this.cancelTask(params);
176
+ case "tasks/list":
177
+ return this.listTasks();
127
178
  default:
128
179
  throw toError(createError({
129
180
  type: "agent",
@@ -137,6 +188,8 @@ export class MCPServer {
137
188
  const negotiated = requested && MCP_SUPPORTED_VERSIONS.includes(requested)
138
189
  ? requested
139
190
  : MCP_SUPPORTED_VERSIONS[0];
191
+ const clientCaps = (p.capabilities ?? {});
192
+ this.clientCapabilities = clientCaps;
140
193
  return Promise.resolve({
141
194
  protocolVersion: negotiated,
142
195
  serverInfo: {
@@ -150,6 +203,8 @@ export class MCPServer {
150
203
  resources: { subscribe: true, listChanged: true },
151
204
  prompts: { listChanged: true },
152
205
  completions: {},
206
+ logging: {},
207
+ tasks: { list: {}, cancel: {}, requests: { tools: { call: {} } } },
153
208
  },
154
209
  instructions: "Veryfront MCP server provides development tools. Use vf_get_errors to check for code errors, vf_get_logs for server logs, vf_scaffold for code generation, and vf_get_project_context for project structure.",
155
210
  });
@@ -183,7 +238,13 @@ export class MCPServer {
183
238
  return { tools };
184
239
  }
185
240
  callTool(params, context) {
186
- const { name, arguments: args } = toParamsRecord(params);
241
+ const p = toParamsRecord(params);
242
+ const { name, arguments: args } = p;
243
+ const meta = (p._meta ?? {});
244
+ const rawToken = meta.progressToken;
245
+ const progressToken = (typeof rawToken === "string" || typeof rawToken === "number")
246
+ ? rawToken
247
+ : undefined;
187
248
  if (!name) {
188
249
  throw toError(createError({ type: "agent", message: "Tool name is required" }));
189
250
  }
@@ -202,9 +263,46 @@ export class MCPServer {
202
263
  throw new JsonRpcError(-32602, `Invalid arguments for tool ${toolName}: ${message}`);
203
264
  }
204
265
  }
266
+ const toolContext = progressToken !== undefined
267
+ ? { ...context, progressToken }
268
+ : context;
269
+ // Async task mode: if the caller provides a `task` field, create a task
270
+ // and run the tool in the background, returning the task immediately.
271
+ const taskParam = p.task;
272
+ if (taskParam) {
273
+ const MIN_TTL = 1000;
274
+ const MAX_TTL = 3_600_000; // 1 hour
275
+ const rawTtl = typeof taskParam.ttl === "number" ? taskParam.ttl : 60000;
276
+ const ttl = Math.max(MIN_TTL, Math.min(MAX_TTL, rawTtl));
277
+ const task = this.taskStore.create(ttl);
278
+ // Run tool in background, update task on completion
279
+ // TODO(#842): wire AbortController so that tasks/cancel actually aborts the running tool execution
280
+ const pending = withSpan("mcp.callTool.async", async () => {
281
+ try {
282
+ const result = await executeTool(toolName, args, toolContext);
283
+ this.taskStore.complete(task.taskId, {
284
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
285
+ isError: false,
286
+ });
287
+ }
288
+ catch (error) {
289
+ const message = error instanceof Error ? error.message : String(error);
290
+ logger.warn("Async tool execution failed", {
291
+ tool: toolName,
292
+ taskId: task.taskId,
293
+ error: message,
294
+ });
295
+ this.taskStore.fail(task.taskId, message);
296
+ }
297
+ }, { "mcp.tool.name": toolName, "mcp.task.id": task.taskId }).then(() => {
298
+ this.pendingTasks.delete(task.taskId);
299
+ });
300
+ this.pendingTasks.set(task.taskId, pending);
301
+ return Promise.resolve({ task });
302
+ }
205
303
  return withSpan("mcp.callTool", async () => {
206
304
  try {
207
- const result = await executeTool(toolName, args, context);
305
+ const result = await executeTool(toolName, args, toolContext);
208
306
  return {
209
307
  content: [{ type: "text", text: JSON.stringify(result, null, 2) }],
210
308
  isError: false,
@@ -327,6 +425,63 @@ export class MCPServer {
327
425
  completion: { values: [], total: 0, hasMore: false },
328
426
  });
329
427
  }
428
+ setLogLevel(params) {
429
+ const p = toParamsRecord(params);
430
+ const level = p.level;
431
+ if (!MCPServer.LOG_LEVELS.includes(level)) {
432
+ return Promise.reject({
433
+ code: -32602,
434
+ message: `Invalid log level: ${level}. Valid levels: ${MCPServer.LOG_LEVELS.join(", ")}`,
435
+ });
436
+ }
437
+ this.logLevel = level;
438
+ return Promise.resolve({});
439
+ }
440
+ getTask(params) {
441
+ const { taskId } = toParamsRecord(params);
442
+ if (!taskId) {
443
+ throw new JsonRpcError(-32602, "taskId is required");
444
+ }
445
+ const task = this.taskStore.get(String(taskId));
446
+ if (!task) {
447
+ throw new JsonRpcError(-32602, `Task not found: ${taskId}`);
448
+ }
449
+ return Promise.resolve({ ...task });
450
+ }
451
+ getTaskResult(params) {
452
+ const { taskId } = toParamsRecord(params);
453
+ if (!taskId) {
454
+ throw new JsonRpcError(-32602, "taskId is required");
455
+ }
456
+ const task = this.taskStore.get(String(taskId));
457
+ if (!task) {
458
+ throw new JsonRpcError(-32602, `Task not found: ${taskId}`);
459
+ }
460
+ const result = this.taskStore.getResult(String(taskId));
461
+ if (result === undefined) {
462
+ throw new JsonRpcError(-32002, "Task result is not yet available");
463
+ }
464
+ return Promise.resolve(result);
465
+ }
466
+ cancelTask(params) {
467
+ const { taskId } = toParamsRecord(params);
468
+ if (!taskId) {
469
+ throw new JsonRpcError(-32602, "taskId is required");
470
+ }
471
+ const cancelled = this.taskStore.cancel(String(taskId));
472
+ if (!cancelled) {
473
+ throw new JsonRpcError(-32002, `Cannot cancel task: ${taskId}`);
474
+ }
475
+ const task = this.taskStore.get(String(taskId));
476
+ return Promise.resolve({ ...task });
477
+ }
478
+ listTasks() {
479
+ return Promise.resolve({ tasks: this.taskStore.list() });
480
+ }
481
+ /** Wait for all background task executions to settle. Useful in tests. */
482
+ waitForPendingTasks() {
483
+ return Promise.all(this.pendingTasks.values()).then(() => { });
484
+ }
330
485
  createHTTPHandler() {
331
486
  return async (request) => {
332
487
  const requestOrigin = request.headers.get("Origin");
@@ -480,6 +635,12 @@ export class MCPServer {
480
635
  };
481
636
  }
482
637
  await syncIntegrationConfig(apiBaseUrl, apiToken, integrationConfigs);
638
+ try {
639
+ this.notifyToolsChanged();
640
+ }
641
+ catch (_) {
642
+ // Notification delivery failure is non-fatal — sync already succeeded
643
+ }
483
644
  return true;
484
645
  }
485
646
  }