@mcpmesh/sdk 0.8.0-beta.1

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 (145) hide show
  1. package/dist/__tests__/claude-handler.test.d.ts +7 -0
  2. package/dist/__tests__/claude-handler.test.d.ts.map +1 -0
  3. package/dist/__tests__/claude-handler.test.js +455 -0
  4. package/dist/__tests__/claude-handler.test.js.map +1 -0
  5. package/dist/__tests__/config.test.d.ts +7 -0
  6. package/dist/__tests__/config.test.d.ts.map +1 -0
  7. package/dist/__tests__/config.test.js +156 -0
  8. package/dist/__tests__/config.test.js.map +1 -0
  9. package/dist/__tests__/errors.test.d.ts +7 -0
  10. package/dist/__tests__/errors.test.d.ts.map +1 -0
  11. package/dist/__tests__/errors.test.js +170 -0
  12. package/dist/__tests__/errors.test.js.map +1 -0
  13. package/dist/__tests__/generic-handler.test.d.ts +7 -0
  14. package/dist/__tests__/generic-handler.test.d.ts.map +1 -0
  15. package/dist/__tests__/generic-handler.test.js +243 -0
  16. package/dist/__tests__/generic-handler.test.js.map +1 -0
  17. package/dist/__tests__/llm-provider.test.d.ts +7 -0
  18. package/dist/__tests__/llm-provider.test.d.ts.map +1 -0
  19. package/dist/__tests__/llm-provider.test.js +217 -0
  20. package/dist/__tests__/llm-provider.test.js.map +1 -0
  21. package/dist/__tests__/openai-handler.test.d.ts +7 -0
  22. package/dist/__tests__/openai-handler.test.d.ts.map +1 -0
  23. package/dist/__tests__/openai-handler.test.js +359 -0
  24. package/dist/__tests__/openai-handler.test.js.map +1 -0
  25. package/dist/__tests__/provider-handler-registry.test.d.ts +9 -0
  26. package/dist/__tests__/provider-handler-registry.test.d.ts.map +1 -0
  27. package/dist/__tests__/provider-handler-registry.test.js +187 -0
  28. package/dist/__tests__/provider-handler-registry.test.js.map +1 -0
  29. package/dist/__tests__/response-parser.test.d.ts +7 -0
  30. package/dist/__tests__/response-parser.test.d.ts.map +1 -0
  31. package/dist/__tests__/response-parser.test.js +360 -0
  32. package/dist/__tests__/response-parser.test.js.map +1 -0
  33. package/dist/__tests__/route.test.d.ts +7 -0
  34. package/dist/__tests__/route.test.d.ts.map +1 -0
  35. package/dist/__tests__/route.test.js +281 -0
  36. package/dist/__tests__/route.test.js.map +1 -0
  37. package/dist/__tests__/sse.test.d.ts +7 -0
  38. package/dist/__tests__/sse.test.d.ts.map +1 -0
  39. package/dist/__tests__/sse.test.js +172 -0
  40. package/dist/__tests__/sse.test.js.map +1 -0
  41. package/dist/__tests__/template.test.d.ts +7 -0
  42. package/dist/__tests__/template.test.d.ts.map +1 -0
  43. package/dist/__tests__/template.test.js +176 -0
  44. package/dist/__tests__/template.test.js.map +1 -0
  45. package/dist/__tests__/tracing.test.d.ts +7 -0
  46. package/dist/__tests__/tracing.test.d.ts.map +1 -0
  47. package/dist/__tests__/tracing.test.js +264 -0
  48. package/dist/__tests__/tracing.test.js.map +1 -0
  49. package/dist/agent.d.ts +165 -0
  50. package/dist/agent.d.ts.map +1 -0
  51. package/dist/agent.js +626 -0
  52. package/dist/agent.js.map +1 -0
  53. package/dist/api-runtime.d.ts +166 -0
  54. package/dist/api-runtime.d.ts.map +1 -0
  55. package/dist/api-runtime.js +459 -0
  56. package/dist/api-runtime.js.map +1 -0
  57. package/dist/config.d.ts +31 -0
  58. package/dist/config.d.ts.map +1 -0
  59. package/dist/config.js +60 -0
  60. package/dist/config.js.map +1 -0
  61. package/dist/debug.d.ts +47 -0
  62. package/dist/debug.d.ts.map +1 -0
  63. package/dist/debug.js +86 -0
  64. package/dist/debug.js.map +1 -0
  65. package/dist/errors.d.ts +99 -0
  66. package/dist/errors.d.ts.map +1 -0
  67. package/dist/errors.js +110 -0
  68. package/dist/errors.js.map +1 -0
  69. package/dist/express.d.ts +146 -0
  70. package/dist/express.d.ts.map +1 -0
  71. package/dist/express.js +371 -0
  72. package/dist/express.js.map +1 -0
  73. package/dist/index.d.ts +96 -0
  74. package/dist/index.d.ts.map +1 -0
  75. package/dist/index.js +107 -0
  76. package/dist/index.js.map +1 -0
  77. package/dist/llm-agent.d.ts +193 -0
  78. package/dist/llm-agent.d.ts.map +1 -0
  79. package/dist/llm-agent.js +634 -0
  80. package/dist/llm-agent.js.map +1 -0
  81. package/dist/llm-provider.d.ts +323 -0
  82. package/dist/llm-provider.d.ts.map +1 -0
  83. package/dist/llm-provider.js +446 -0
  84. package/dist/llm-provider.js.map +1 -0
  85. package/dist/llm.d.ts +194 -0
  86. package/dist/llm.d.ts.map +1 -0
  87. package/dist/llm.js +304 -0
  88. package/dist/llm.js.map +1 -0
  89. package/dist/provider-handlers/claude-handler.d.ts +98 -0
  90. package/dist/provider-handlers/claude-handler.d.ts.map +1 -0
  91. package/dist/provider-handlers/claude-handler.js +268 -0
  92. package/dist/provider-handlers/claude-handler.js.map +1 -0
  93. package/dist/provider-handlers/gemini-handler.d.ts +82 -0
  94. package/dist/provider-handlers/gemini-handler.d.ts.map +1 -0
  95. package/dist/provider-handlers/gemini-handler.js +152 -0
  96. package/dist/provider-handlers/gemini-handler.js.map +1 -0
  97. package/dist/provider-handlers/generic-handler.d.ts +78 -0
  98. package/dist/provider-handlers/generic-handler.d.ts.map +1 -0
  99. package/dist/provider-handlers/generic-handler.js +152 -0
  100. package/dist/provider-handlers/generic-handler.js.map +1 -0
  101. package/dist/provider-handlers/index.d.ts +29 -0
  102. package/dist/provider-handlers/index.d.ts.map +1 -0
  103. package/dist/provider-handlers/index.js +32 -0
  104. package/dist/provider-handlers/index.js.map +1 -0
  105. package/dist/provider-handlers/openai-handler.d.ts +86 -0
  106. package/dist/provider-handlers/openai-handler.d.ts.map +1 -0
  107. package/dist/provider-handlers/openai-handler.js +160 -0
  108. package/dist/provider-handlers/openai-handler.js.map +1 -0
  109. package/dist/provider-handlers/provider-handler-registry.d.ts +124 -0
  110. package/dist/provider-handlers/provider-handler-registry.d.ts.map +1 -0
  111. package/dist/provider-handlers/provider-handler-registry.js +180 -0
  112. package/dist/provider-handlers/provider-handler-registry.js.map +1 -0
  113. package/dist/provider-handlers/provider-handler.d.ts +245 -0
  114. package/dist/provider-handlers/provider-handler.d.ts.map +1 -0
  115. package/dist/provider-handlers/provider-handler.js +238 -0
  116. package/dist/provider-handlers/provider-handler.js.map +1 -0
  117. package/dist/proxy.d.ts +44 -0
  118. package/dist/proxy.d.ts.map +1 -0
  119. package/dist/proxy.js +324 -0
  120. package/dist/proxy.js.map +1 -0
  121. package/dist/response-parser.d.ts +103 -0
  122. package/dist/response-parser.d.ts.map +1 -0
  123. package/dist/response-parser.js +232 -0
  124. package/dist/response-parser.js.map +1 -0
  125. package/dist/route.d.ts +185 -0
  126. package/dist/route.d.ts.map +1 -0
  127. package/dist/route.js +310 -0
  128. package/dist/route.js.map +1 -0
  129. package/dist/sse.d.ts +45 -0
  130. package/dist/sse.d.ts.map +1 -0
  131. package/dist/sse.js +77 -0
  132. package/dist/sse.js.map +1 -0
  133. package/dist/template.d.ts +86 -0
  134. package/dist/template.d.ts.map +1 -0
  135. package/dist/template.js +206 -0
  136. package/dist/template.js.map +1 -0
  137. package/dist/tracing.d.ts +88 -0
  138. package/dist/tracing.d.ts.map +1 -0
  139. package/dist/tracing.js +193 -0
  140. package/dist/tracing.js.map +1 -0
  141. package/dist/types.d.ts +618 -0
  142. package/dist/types.d.ts.map +1 -0
  143. package/dist/types.js +5 -0
  144. package/dist/types.js.map +1 -0
  145. package/package.json +68 -0
package/dist/llm.js ADDED
@@ -0,0 +1,304 @@
1
+ /**
2
+ * mesh.llm() - LLM-powered tool wrapper for MCP Mesh.
3
+ *
4
+ * Creates a tool that uses an LLM with agentic capabilities,
5
+ * including access to other mesh tools and structured output.
6
+ *
7
+ * @example
8
+ * ```typescript
9
+ * import { FastMCP } from "fastmcp";
10
+ * import { mesh } from "@mcpmesh/sdk";
11
+ * import { z } from "zod";
12
+ *
13
+ * const server = new FastMCP({ name: "Smart Assistant", version: "1.0.0" });
14
+ *
15
+ * const AssistResponse = z.object({
16
+ * answer: z.string(),
17
+ * confidence: z.number(),
18
+ * });
19
+ *
20
+ * server.addTool(mesh.llm({
21
+ * name: "assist",
22
+ * capability: "smart_assistant",
23
+ * provider: "claude",
24
+ * systemPrompt: "file://prompts/assistant.hbs",
25
+ * filter: [{ capability: "calculator" }],
26
+ * returns: AssistResponse,
27
+ * parameters: z.object({ message: z.string() }),
28
+ * execute: async ({ message }, { llm }) => llm(message),
29
+ * }));
30
+ *
31
+ * const agent = mesh(server, { name: "smart-assistant", port: 9003 });
32
+ * ```
33
+ */
34
+ import { zodToJsonSchema } from "zod-to-json-schema";
35
+ import { MeshLlmAgent, createLlmToolProxy } from "./llm-agent.js";
36
+ import { debug } from "./debug.js";
37
+ /**
38
+ * Registry for LLM tools - stores configuration and resolved dependencies.
39
+ */
40
+ export class LlmToolRegistry {
41
+ static instance = null;
42
+ /** LLM tool configurations by function ID */
43
+ configs = new Map();
44
+ /** Resolved tools for each LLM function (from llm_tools_updated events) */
45
+ resolvedTools = new Map();
46
+ /** Resolved providers for each LLM function (from llm_provider_available events) */
47
+ resolvedProviders = new Map();
48
+ constructor() { }
49
+ static getInstance() {
50
+ if (!LlmToolRegistry.instance) {
51
+ LlmToolRegistry.instance = new LlmToolRegistry();
52
+ }
53
+ return LlmToolRegistry.instance;
54
+ }
55
+ /**
56
+ * Reset the registry (for testing).
57
+ */
58
+ static reset() {
59
+ LlmToolRegistry.instance = null;
60
+ }
61
+ /**
62
+ * Register an LLM tool configuration.
63
+ */
64
+ register(functionId, config) {
65
+ this.configs.set(functionId, config);
66
+ }
67
+ /**
68
+ * Get an LLM tool configuration.
69
+ */
70
+ getConfig(functionId) {
71
+ return this.configs.get(functionId);
72
+ }
73
+ /**
74
+ * Get all registered LLM tool configurations.
75
+ */
76
+ getAllConfigs() {
77
+ return new Map(this.configs);
78
+ }
79
+ /**
80
+ * Update resolved tools for an LLM function.
81
+ */
82
+ setResolvedTools(functionId, tools) {
83
+ this.resolvedTools.set(functionId, tools);
84
+ debug.llm(`Tools updated for ${functionId}: ${tools.length} tools available`);
85
+ }
86
+ /**
87
+ * Get resolved tools for an LLM function.
88
+ */
89
+ getResolvedTools(functionId) {
90
+ return this.resolvedTools.get(functionId) ?? [];
91
+ }
92
+ /**
93
+ * Update resolved provider for an LLM function.
94
+ */
95
+ setResolvedProvider(functionId, provider) {
96
+ this.resolvedProviders.set(functionId, provider);
97
+ debug.llm(`Provider available for ${functionId}: ${provider.endpoint}`);
98
+ }
99
+ /**
100
+ * Remove resolved provider for an LLM function.
101
+ */
102
+ removeResolvedProvider(functionId) {
103
+ this.resolvedProviders.delete(functionId);
104
+ debug.llm(`Provider unavailable for ${functionId}`);
105
+ }
106
+ /**
107
+ * Get resolved provider for an LLM function.
108
+ */
109
+ getResolvedProvider(functionId) {
110
+ return this.resolvedProviders.get(functionId);
111
+ }
112
+ /**
113
+ * Clear all resolved dependencies.
114
+ */
115
+ clearAllResolved() {
116
+ this.resolvedTools.clear();
117
+ this.resolvedProviders.clear();
118
+ }
119
+ }
120
+ /**
121
+ * Create an LLM-powered tool definition.
122
+ *
123
+ * This function returns a fastmcp-compatible tool definition that can be
124
+ * passed to server.addTool(). The tool will use an LLM with agentic capabilities.
125
+ *
126
+ * @param config - LLM tool configuration
127
+ * @returns fastmcp tool definition
128
+ */
129
+ export function llm(config) {
130
+ const registry = LlmToolRegistry.getInstance();
131
+ // Generate function ID
132
+ const functionId = config.name;
133
+ // Normalize configuration
134
+ const llmConfig = {
135
+ functionId,
136
+ name: config.name,
137
+ capability: config.capability ?? config.name,
138
+ description: config.description ?? "",
139
+ version: config.version ?? "1.0.0",
140
+ tags: config.tags ?? [],
141
+ provider: config.provider,
142
+ model: config.model,
143
+ maxIterations: config.maxIterations ?? 10,
144
+ systemPrompt: config.systemPrompt,
145
+ contextParam: config.contextParam,
146
+ filter: config.filter,
147
+ filterMode: config.filterMode ?? "all",
148
+ maxOutputTokens: config.maxOutputTokens,
149
+ temperature: config.temperature,
150
+ topP: config.topP,
151
+ stop: config.stop,
152
+ inputSchema: JSON.stringify(zodToJsonSchema(config.parameters, { $refStrategy: "none" })),
153
+ returnSchema: config.returns,
154
+ outputMode: config.outputMode ?? "hint",
155
+ execute: config.execute,
156
+ };
157
+ // Register with LLM tool registry
158
+ registry.register(functionId, llmConfig);
159
+ // Create MeshLlmAgent once (cached for reuse)
160
+ const agent = new MeshLlmAgent({
161
+ functionId,
162
+ provider: llmConfig.provider,
163
+ model: llmConfig.model,
164
+ systemPrompt: llmConfig.systemPrompt,
165
+ contextParam: llmConfig.contextParam,
166
+ maxIterations: llmConfig.maxIterations,
167
+ maxOutputTokens: llmConfig.maxOutputTokens,
168
+ temperature: llmConfig.temperature,
169
+ topP: llmConfig.topP,
170
+ stop: llmConfig.stop,
171
+ returnSchema: llmConfig.returnSchema,
172
+ outputMode: llmConfig.outputMode,
173
+ });
174
+ // Create the execute wrapper
175
+ const wrappedExecute = async (args) => {
176
+ try {
177
+ debug.llm(`Executing ${functionId} with args:`, JSON.stringify(args));
178
+ // Get resolved tools and provider
179
+ const tools = registry.getResolvedTools(functionId);
180
+ const meshProvider = registry.getResolvedProvider(functionId);
181
+ debug.llm(`Tools: ${tools.length}, Provider:`, meshProvider ? meshProvider.endpoint : "none");
182
+ // Extract template context from args if contextParam is specified
183
+ let templateContext = {};
184
+ if (llmConfig.contextParam && args && typeof args === "object") {
185
+ const argsObj = args;
186
+ if (argsObj[llmConfig.contextParam]) {
187
+ templateContext = argsObj[llmConfig.contextParam];
188
+ }
189
+ }
190
+ // Create callable LLM agent
191
+ const llmCallable = agent.createCallable({
192
+ tools,
193
+ meshProvider: meshProvider
194
+ ? {
195
+ endpoint: meshProvider.endpoint,
196
+ functionName: meshProvider.functionName,
197
+ model: meshProvider.model,
198
+ }
199
+ : undefined,
200
+ templateContext,
201
+ });
202
+ // Call user's execute handler
203
+ debug.llm(`Calling user execute handler`);
204
+ const result = await llmConfig.execute(args, { llm: llmCallable });
205
+ debug.llm(`Execute completed successfully`);
206
+ // Convert result to string for MCP
207
+ if (typeof result === "string") {
208
+ return result;
209
+ }
210
+ return JSON.stringify(result);
211
+ }
212
+ catch (error) {
213
+ debug.llm(`Error in ${functionId}:`, error);
214
+ throw error;
215
+ }
216
+ };
217
+ // Return fastmcp-compatible tool definition with mesh metadata
218
+ return {
219
+ name: config.name,
220
+ description: config.description,
221
+ parameters: config.parameters,
222
+ execute: wrappedExecute,
223
+ _meshLlmConfig: llmConfig,
224
+ };
225
+ }
226
+ /**
227
+ * Build JsLlmAgentSpec for Rust core from LLM tool configs.
228
+ */
229
+ export function buildLlmAgentSpecs() {
230
+ const registry = LlmToolRegistry.getInstance();
231
+ const specs = [];
232
+ for (const [, config] of registry.getAllConfigs()) {
233
+ // Serialize provider to JSON
234
+ const providerJson = typeof config.provider === "string"
235
+ ? JSON.stringify({ direct: config.provider })
236
+ : JSON.stringify(config.provider);
237
+ // Serialize filter to JSON if present
238
+ const filterJson = config.filter ? JSON.stringify(config.filter) : undefined;
239
+ specs.push({
240
+ functionId: config.functionId,
241
+ provider: providerJson,
242
+ filter: filterJson,
243
+ filterMode: config.filterMode,
244
+ maxIterations: config.maxIterations,
245
+ });
246
+ }
247
+ return specs;
248
+ }
249
+ /**
250
+ * Handle llm_tools_updated event from Rust core.
251
+ */
252
+ export function handleLlmToolsUpdated(functionId, tools) {
253
+ const registry = LlmToolRegistry.getInstance();
254
+ // Create tool proxies
255
+ const proxies = tools.map((tool) => createLlmToolProxy(tool));
256
+ // Update registry
257
+ registry.setResolvedTools(functionId, proxies);
258
+ }
259
+ /**
260
+ * Handle llm_provider_available event from Rust core.
261
+ */
262
+ export function handleLlmProviderAvailable(functionId, providerInfo) {
263
+ debug.llm(`Provider available for ${functionId}: ${providerInfo.endpoint}/${providerInfo.functionName}`);
264
+ const registry = LlmToolRegistry.getInstance();
265
+ registry.setResolvedProvider(functionId, {
266
+ endpoint: providerInfo.endpoint,
267
+ functionName: providerInfo.functionName,
268
+ model: providerInfo.model,
269
+ agentId: providerInfo.agentId,
270
+ });
271
+ debug.llm(`Provider stored for ${functionId}`);
272
+ }
273
+ /**
274
+ * Handle llm_provider_unavailable event from Rust core.
275
+ */
276
+ export function handleLlmProviderUnavailable(functionId) {
277
+ const registry = LlmToolRegistry.getInstance();
278
+ registry.removeResolvedProvider(functionId);
279
+ }
280
+ /**
281
+ * Get LLM tool metadata for JsToolSpec.
282
+ */
283
+ export function getLlmToolMetadata(toolName) {
284
+ const registry = LlmToolRegistry.getInstance();
285
+ const config = registry.getConfig(toolName);
286
+ if (!config) {
287
+ return null;
288
+ }
289
+ return {
290
+ llmFilter: config.filter ? JSON.stringify(config.filter) : undefined,
291
+ llmProvider: typeof config.provider === "string"
292
+ ? config.provider
293
+ : JSON.stringify(config.provider),
294
+ };
295
+ }
296
+ /**
297
+ * Check if a tool is an LLM tool.
298
+ */
299
+ export function isLlmTool(toolDef) {
300
+ return (typeof toolDef === "object" &&
301
+ toolDef !== null &&
302
+ "_meshLlmConfig" in toolDef);
303
+ }
304
+ //# sourceMappingURL=llm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"llm.js","sourceRoot":"","sources":["../src/llm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Claude/Anthropic provider handler.
3
+ *
4
+ * Optimized for Claude API (Claude 3.x, Sonnet, Opus, Haiku)
5
+ * using Anthropic's best practices for tool calling and JSON responses.
6
+ *
7
+ * Supports three output modes for performance/reliability tradeoffs:
8
+ * - strict: Use response_format for guaranteed schema compliance (slowest, 100% reliable)
9
+ * - hint: Use prompt-based JSON instructions (medium speed, ~95% reliable)
10
+ * - text: Plain text output for str return types (fastest)
11
+ *
12
+ * Features:
13
+ * - Anti-XML tool calling instructions
14
+ * - Output mode optimization based on return type
15
+ *
16
+ * Note: Prompt caching is not yet implemented for AI SDK v6.
17
+ * TODO: Re-enable via experimental_providerOptions when AI SDK v6 supports it.
18
+ *
19
+ * Based on Python's ClaudeHandler:
20
+ * src/runtime/python/_mcp_mesh/engine/provider_handlers/claude_handler.py
21
+ */
22
+ import type { LlmMessage } from "../types.js";
23
+ import { type ProviderHandler, type VendorCapabilities, type ToolSchema, type OutputSchema, type PreparedRequest, type OutputMode } from "./provider-handler.js";
24
+ /**
25
+ * Provider handler for Claude/Anthropic models.
26
+ *
27
+ * Claude Characteristics:
28
+ * - Excellent at following detailed instructions
29
+ * - Native structured output via response_format (requires strict schema)
30
+ * - Native tool calling (via Anthropic messages API)
31
+ * - Performs best with anti-XML tool calling instructions
32
+ *
33
+ * Output Modes:
34
+ * - strict: response_format with JSON schema (slowest, guaranteed valid JSON)
35
+ * - hint: JSON schema in prompt (medium speed, usually valid JSON)
36
+ * - text: Plain text output for str return types (fastest)
37
+ *
38
+ * Best Practices (from Anthropic docs):
39
+ * - Use response_format for guaranteed JSON schema compliance
40
+ * - Schema must have additionalProperties: false on all objects
41
+ * - Add anti-XML instructions to prevent <invoke> style tool calls
42
+ * - Use one tool call at a time for better reliability
43
+ */
44
+ export declare class ClaudeHandler implements ProviderHandler {
45
+ readonly vendor = "anthropic";
46
+ /**
47
+ * Prepare request parameters for Claude API with output mode support.
48
+ *
49
+ * Output Mode Strategy:
50
+ * - strict: Use response_format for guaranteed JSON schema compliance (slowest)
51
+ * - hint: No response_format, rely on prompt instructions (medium speed)
52
+ * - text: No response_format, plain text output (fastest)
53
+ *
54
+ * Message Format (Anthropic-specific):
55
+ * - Assistant messages with tool_calls → content blocks with type "tool-call"
56
+ * - Tool result messages → content blocks with type "tool-result"
57
+ * This is required for Vercel AI SDK to properly convert to Anthropic's native format.
58
+ */
59
+ prepareRequest(messages: LlmMessage[], tools: ToolSchema[] | null, outputSchema: OutputSchema | null, options?: {
60
+ outputMode?: OutputMode;
61
+ temperature?: number;
62
+ maxOutputTokens?: number;
63
+ topP?: number;
64
+ [key: string]: unknown;
65
+ }): PreparedRequest;
66
+ /**
67
+ * Format system prompt for Claude with output mode support.
68
+ *
69
+ * Output Mode Strategy:
70
+ * - strict: Minimal JSON instructions (response_format handles schema)
71
+ * - hint: Add detailed JSON schema instructions in prompt
72
+ * - text: No JSON instructions (plain text output)
73
+ */
74
+ formatSystemPrompt(basePrompt: string, toolSchemas: ToolSchema[] | null, outputSchema: OutputSchema | null, outputMode?: OutputMode): string;
75
+ /**
76
+ * Return Claude-specific capabilities.
77
+ */
78
+ getCapabilities(): VendorCapabilities;
79
+ /**
80
+ * Determine the output mode based on schema complexity.
81
+ *
82
+ * Logic:
83
+ * - If overrideMode specified, use it
84
+ * - If no schema (string return type), use "text" mode
85
+ * - If schema is simple (<5 fields, basic types), use "hint" mode
86
+ * - Otherwise, use "strict" mode
87
+ */
88
+ determineOutputMode(outputSchema: OutputSchema | null, overrideMode?: OutputMode): OutputMode;
89
+ /**
90
+ * Check if a schema is simple enough for hint mode.
91
+ *
92
+ * Simple schema criteria:
93
+ * - Less than 5 fields
94
+ * - No nested objects (hasNestedObjects flag or $defs present)
95
+ */
96
+ private isSimpleSchema;
97
+ }
98
+ //# sourceMappingURL=claude-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-handler.d.ts","sourceRoot":"","sources":["../../src/provider-handlers/claude-handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAKL,KAAK,eAAe,EACpB,KAAK,kBAAkB,EACvB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,UAAU,EAChB,MAAM,uBAAuB,CAAC;AAgB/B;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,aAAc,YAAW,eAAe;IACnD,QAAQ,CAAC,MAAM,eAAe;IAE9B;;;;;;;;;;;;OAYG;IACH,cAAc,CACZ,QAAQ,EAAE,UAAU,EAAE,EACtB,KAAK,EAAE,UAAU,EAAE,GAAG,IAAI,EAC1B,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;KACxB,GACA,eAAe;IAgDlB;;;;;;;OAOG;IACH,kBAAkB,CAChB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,UAAU,EAAE,GAAG,IAAI,EAChC,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,UAAU,CAAC,EAAE,UAAU,GACtB,MAAM;IAqET;;OAEG;IACH,eAAe,IAAI,kBAAkB;IAWrC;;;;;;;;OAQG;IACH,mBAAmB,CACjB,YAAY,EAAE,YAAY,GAAG,IAAI,EACjC,YAAY,CAAC,EAAE,UAAU,GACxB,UAAU;IAwBb;;;;;;OAMG;IACH,OAAO,CAAC,cAAc;CAkDvB"}
@@ -0,0 +1,268 @@
1
+ /**
2
+ * Claude/Anthropic provider handler.
3
+ *
4
+ * Optimized for Claude API (Claude 3.x, Sonnet, Opus, Haiku)
5
+ * using Anthropic's best practices for tool calling and JSON responses.
6
+ *
7
+ * Supports three output modes for performance/reliability tradeoffs:
8
+ * - strict: Use response_format for guaranteed schema compliance (slowest, 100% reliable)
9
+ * - hint: Use prompt-based JSON instructions (medium speed, ~95% reliable)
10
+ * - text: Plain text output for str return types (fastest)
11
+ *
12
+ * Features:
13
+ * - Anti-XML tool calling instructions
14
+ * - Output mode optimization based on return type
15
+ *
16
+ * Note: Prompt caching is not yet implemented for AI SDK v6.
17
+ * TODO: Re-enable via experimental_providerOptions when AI SDK v6 supports it.
18
+ *
19
+ * Based on Python's ClaudeHandler:
20
+ * src/runtime/python/_mcp_mesh/engine/provider_handlers/claude_handler.py
21
+ */
22
+ import { createDebug } from "../debug.js";
23
+ import { convertMessagesToVercelFormat, makeSchemaStrict, BASE_TOOL_INSTRUCTIONS, CLAUDE_ANTI_XML_INSTRUCTION, } from "./provider-handler.js";
24
+ import { ProviderHandlerRegistry } from "./provider-handler-registry.js";
25
+ const debug = createDebug("claude-handler");
26
+ // ============================================================================
27
+ // Constants
28
+ // ============================================================================
29
+ /** Simple schema threshold - schemas with fewer fields use hint mode */
30
+ const SIMPLE_SCHEMA_FIELD_THRESHOLD = 5;
31
+ // ============================================================================
32
+ // Claude Handler Implementation
33
+ // ============================================================================
34
+ /**
35
+ * Provider handler for Claude/Anthropic models.
36
+ *
37
+ * Claude Characteristics:
38
+ * - Excellent at following detailed instructions
39
+ * - Native structured output via response_format (requires strict schema)
40
+ * - Native tool calling (via Anthropic messages API)
41
+ * - Performs best with anti-XML tool calling instructions
42
+ *
43
+ * Output Modes:
44
+ * - strict: response_format with JSON schema (slowest, guaranteed valid JSON)
45
+ * - hint: JSON schema in prompt (medium speed, usually valid JSON)
46
+ * - text: Plain text output for str return types (fastest)
47
+ *
48
+ * Best Practices (from Anthropic docs):
49
+ * - Use response_format for guaranteed JSON schema compliance
50
+ * - Schema must have additionalProperties: false on all objects
51
+ * - Add anti-XML instructions to prevent <invoke> style tool calls
52
+ * - Use one tool call at a time for better reliability
53
+ */
54
+ export class ClaudeHandler {
55
+ vendor = "anthropic";
56
+ /**
57
+ * Prepare request parameters for Claude API with output mode support.
58
+ *
59
+ * Output Mode Strategy:
60
+ * - strict: Use response_format for guaranteed JSON schema compliance (slowest)
61
+ * - hint: No response_format, rely on prompt instructions (medium speed)
62
+ * - text: No response_format, plain text output (fastest)
63
+ *
64
+ * Message Format (Anthropic-specific):
65
+ * - Assistant messages with tool_calls → content blocks with type "tool-call"
66
+ * - Tool result messages → content blocks with type "tool-result"
67
+ * This is required for Vercel AI SDK to properly convert to Anthropic's native format.
68
+ */
69
+ prepareRequest(messages, tools, outputSchema, options) {
70
+ const { outputMode, temperature, maxOutputTokens: maxTokens, topP, ...rest } = options ?? {};
71
+ const determinedMode = this.determineOutputMode(outputSchema, outputMode);
72
+ // Convert messages to Vercel AI SDK format (shared utility)
73
+ const convertedMessages = convertMessagesToVercelFormat(messages);
74
+ const request = {
75
+ messages: convertedMessages,
76
+ ...rest,
77
+ };
78
+ // Add tools if provided
79
+ // Vercel AI SDK will convert OpenAI tool format to Anthropic's format
80
+ if (tools && tools.length > 0) {
81
+ request.tools = tools;
82
+ }
83
+ // Add standard parameters if provided
84
+ if (temperature !== undefined) {
85
+ request.temperature = temperature;
86
+ }
87
+ if (maxTokens !== undefined) {
88
+ request.maxOutputTokens = maxTokens;
89
+ }
90
+ if (topP !== undefined) {
91
+ request.topP = topP;
92
+ }
93
+ // Only add response_format in "strict" mode
94
+ if (determinedMode === "strict" && outputSchema) {
95
+ // Claude requires additionalProperties: false on all object types
96
+ // Unlike OpenAI/Gemini, Claude doesn't require all properties in 'required'
97
+ const strictSchema = makeSchemaStrict(outputSchema.schema, { addAllRequired: false });
98
+ request.responseFormat = {
99
+ type: "json_schema",
100
+ jsonSchema: {
101
+ name: outputSchema.name,
102
+ schema: strictSchema,
103
+ strict: false, // Allow optional fields with defaults
104
+ },
105
+ };
106
+ debug(`Using strict mode with response_format for schema: ${outputSchema.name}`);
107
+ }
108
+ return request;
109
+ }
110
+ /**
111
+ * Format system prompt for Claude with output mode support.
112
+ *
113
+ * Output Mode Strategy:
114
+ * - strict: Minimal JSON instructions (response_format handles schema)
115
+ * - hint: Add detailed JSON schema instructions in prompt
116
+ * - text: No JSON instructions (plain text output)
117
+ */
118
+ formatSystemPrompt(basePrompt, toolSchemas, outputSchema, outputMode) {
119
+ let systemContent = basePrompt;
120
+ const determinedMode = this.determineOutputMode(outputSchema, outputMode);
121
+ // Add tool calling instructions if tools available
122
+ // These prevent Claude from using XML-style <invoke> syntax
123
+ if (toolSchemas && toolSchemas.length > 0) {
124
+ // Use base instructions but insert anti-XML rule for Claude
125
+ const instructions = BASE_TOOL_INSTRUCTIONS.replace("- Make ONE tool call at a time", `- Make ONE tool call at a time\n${CLAUDE_ANTI_XML_INSTRUCTION}`);
126
+ systemContent += instructions;
127
+ }
128
+ // Add output format instructions based on mode
129
+ if (determinedMode === "text") {
130
+ // Text mode: No JSON instructions
131
+ return systemContent;
132
+ }
133
+ if (determinedMode === "strict") {
134
+ // Strict mode: Minimal instructions (response_format handles schema)
135
+ if (outputSchema) {
136
+ systemContent += `
137
+
138
+ Your final response will be structured as JSON matching the ${outputSchema.name} format.`;
139
+ }
140
+ return systemContent;
141
+ }
142
+ // Hint mode: Add detailed JSON schema instructions
143
+ if (determinedMode === "hint" && outputSchema) {
144
+ const properties = (outputSchema.schema.properties ?? {});
145
+ const required = (outputSchema.schema.required ?? []);
146
+ // Build human-readable schema description
147
+ const fieldDescriptions = [];
148
+ for (const [fieldName, fieldSchema] of Object.entries(properties)) {
149
+ const fieldType = fieldSchema.type ?? "any";
150
+ const isRequired = required.includes(fieldName);
151
+ const reqMarker = isRequired ? " (required)" : " (optional)";
152
+ const desc = fieldSchema.description ?? "";
153
+ const descText = desc ? ` - ${desc}` : "";
154
+ fieldDescriptions.push(` - ${fieldName}: ${fieldType}${reqMarker}${descText}`);
155
+ }
156
+ const fieldsText = fieldDescriptions.join("\n");
157
+ const exampleFormat = Object.fromEntries(Object.entries(properties).map(([k, v]) => [k, `<${v.type ?? "value"}>`]));
158
+ systemContent += `
159
+
160
+ RESPONSE FORMAT:
161
+ You MUST respond with valid JSON matching this schema:
162
+ {
163
+ ${fieldsText}
164
+ }
165
+
166
+ Example format:
167
+ ${JSON.stringify(exampleFormat, null, 2)}
168
+
169
+ IMPORTANT: Respond ONLY with valid JSON. No markdown code fences, no preamble text.`;
170
+ }
171
+ return systemContent;
172
+ }
173
+ /**
174
+ * Return Claude-specific capabilities.
175
+ */
176
+ getCapabilities() {
177
+ return {
178
+ nativeToolCalling: true, // Claude has native function calling
179
+ structuredOutput: true, // Native response_format support via Vercel AI SDK
180
+ streaming: true, // Supports streaming
181
+ vision: true, // Claude 3+ supports vision
182
+ jsonMode: true, // Native JSON mode via response_format
183
+ promptCaching: false, // TODO: Re-enable via experimental_providerOptions
184
+ };
185
+ }
186
+ /**
187
+ * Determine the output mode based on schema complexity.
188
+ *
189
+ * Logic:
190
+ * - If overrideMode specified, use it
191
+ * - If no schema (string return type), use "text" mode
192
+ * - If schema is simple (<5 fields, basic types), use "hint" mode
193
+ * - Otherwise, use "strict" mode
194
+ */
195
+ determineOutputMode(outputSchema, overrideMode) {
196
+ // Allow explicit override
197
+ if (overrideMode) {
198
+ return overrideMode;
199
+ }
200
+ // No schema means text mode (string return type)
201
+ if (!outputSchema) {
202
+ return "text";
203
+ }
204
+ // Check if schema is simple
205
+ if (this.isSimpleSchema(outputSchema)) {
206
+ return "hint";
207
+ }
208
+ // Complex schema - use strict mode
209
+ return "strict";
210
+ }
211
+ // ==========================================================================
212
+ // Private Helper Methods
213
+ // ==========================================================================
214
+ /**
215
+ * Check if a schema is simple enough for hint mode.
216
+ *
217
+ * Simple schema criteria:
218
+ * - Less than 5 fields
219
+ * - No nested objects (hasNestedObjects flag or $defs present)
220
+ */
221
+ isSimpleSchema(outputSchema) {
222
+ // Use pre-computed values if available
223
+ if (outputSchema.fieldCount !== undefined) {
224
+ if (outputSchema.fieldCount >= SIMPLE_SCHEMA_FIELD_THRESHOLD) {
225
+ return false;
226
+ }
227
+ }
228
+ if (outputSchema.hasNestedObjects !== undefined) {
229
+ return !outputSchema.hasNestedObjects;
230
+ }
231
+ // Analyze schema directly
232
+ const schema = outputSchema.schema;
233
+ const properties = schema.properties;
234
+ // Check field count
235
+ if (properties && Object.keys(properties).length >= SIMPLE_SCHEMA_FIELD_THRESHOLD) {
236
+ return false;
237
+ }
238
+ // Check for $defs (indicates nested models)
239
+ if (schema.$defs) {
240
+ return false;
241
+ }
242
+ // Check for nested objects in properties
243
+ if (properties) {
244
+ for (const fieldSchema of Object.values(properties)) {
245
+ const fs = fieldSchema;
246
+ // Check for nested objects
247
+ if (fs.type === "object" && fs.properties) {
248
+ return false;
249
+ }
250
+ // Check for $ref (nested model reference)
251
+ if (fs.$ref) {
252
+ return false;
253
+ }
254
+ // Check array items for complex types
255
+ if (fs.type === "array") {
256
+ const items = fs.items;
257
+ if (items?.type === "object" || items?.$ref) {
258
+ return false;
259
+ }
260
+ }
261
+ }
262
+ }
263
+ return true;
264
+ }
265
+ }
266
+ // Register with the registry
267
+ ProviderHandlerRegistry.register("anthropic", ClaudeHandler);
268
+ //# sourceMappingURL=claude-handler.js.map