@hailer/mcp 1.0.24 → 1.0.25

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.
@@ -113,6 +113,21 @@ export declare class ToolRegistry {
113
113
  * Get tool metadata (for access control checks)
114
114
  */
115
115
  getTool(name: string): Tool | undefined;
116
+ /**
117
+ * Get tools with their original Zod schemas for MCP SDK registration.
118
+ * MCP SDK requires Zod schemas, not JSON Schema objects.
119
+ *
120
+ * @param filter - Optional filter configuration
121
+ * @returns Array of tools with name, description, and Zod schema
122
+ */
123
+ getToolsWithZodSchemas(filter?: {
124
+ allowedGroups?: ToolGroup[];
125
+ allowedTools?: string[];
126
+ }): Array<{
127
+ name: string;
128
+ description: string;
129
+ schema: z.ZodType;
130
+ }>;
116
131
  /**
117
132
  * Get total tool count
118
133
  */
@@ -324,6 +324,29 @@ Then retry \`${name}\` with the correct format from the skill examples.` : `💡
324
324
  getTool(name) {
325
325
  return this.tools.get(name);
326
326
  }
327
+ /**
328
+ * Get tools with their original Zod schemas for MCP SDK registration.
329
+ * MCP SDK requires Zod schemas, not JSON Schema objects.
330
+ *
331
+ * @param filter - Optional filter configuration
332
+ * @returns Array of tools with name, description, and Zod schema
333
+ */
334
+ getToolsWithZodSchemas(filter) {
335
+ let toolsToExpose = Array.from(this.tools.values());
336
+ if (filter) {
337
+ if (filter.allowedTools) {
338
+ toolsToExpose = toolsToExpose.filter(t => filter.allowedTools.includes(t.name));
339
+ }
340
+ else if (filter.allowedGroups) {
341
+ toolsToExpose = toolsToExpose.filter(t => filter.allowedGroups.includes(t.group));
342
+ }
343
+ }
344
+ return toolsToExpose.map(tool => ({
345
+ name: tool.name,
346
+ description: tool.description,
347
+ schema: tool.schema
348
+ }));
349
+ }
327
350
  /**
328
351
  * Get total tool count
329
352
  */
@@ -36,23 +36,36 @@ async function startStdioServer(toolRegistry) {
36
36
  const allowedGroups = config_1.environment.ENABLE_NUCLEAR_TOOLS
37
37
  ? [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.PLAYGROUND, tool_registry_1.ToolGroup.NUCLEAR]
38
38
  : [tool_registry_1.ToolGroup.READ, tool_registry_1.ToolGroup.WRITE, tool_registry_1.ToolGroup.PLAYGROUND];
39
- const toolDefinitions = toolRegistry.getToolDefinitions({ allowedGroups });
39
+ // Get tools with their original Zod schemas - MCP SDK requires Zod, not JSON Schema
40
+ const tools = toolRegistry.getToolsWithZodSchemas({ allowedGroups });
40
41
  logger.info('Registering tools for stdio server', {
41
- toolCount: toolDefinitions.length,
42
+ toolCount: tools.length,
42
43
  allowedGroups,
43
44
  });
44
- // Register each tool with the MCP server
45
- for (const toolDef of toolDefinitions) {
46
- server.tool(toolDef.name, toolDef.description, toolDef.inputSchema.properties ? toolDef.inputSchema : { type: 'object', properties: {} }, async (args) => {
45
+ // Register each tool with the MCP server using Zod schemas
46
+ for (const tool of tools) {
47
+ // Extract shape from ZodObject for MCP SDK compatibility
48
+ // MCP SDK expects a "raw shape" (object with Zod types as values), not a ZodObject
49
+ const zodSchema = tool.schema;
50
+ const shape = zodSchema._def?.typeName === 'ZodObject'
51
+ ? zodSchema._def.shape()
52
+ : zodSchema;
53
+ logger.debug('Registering tool with Zod schema', {
54
+ name: tool.name,
55
+ schemaTypeName: zodSchema._def?.typeName || 'unknown',
56
+ shapeKeys: Object.keys(shape || {})
57
+ });
58
+ // Use tool() method with shape object - MCP SDK will recognize Zod types
59
+ server.tool(tool.name, tool.description, shape, async (args) => {
47
60
  const startTime = Date.now();
48
- logger.debug('Tool call received', { toolName: toolDef.name, args });
61
+ logger.debug('Tool call received', { toolName: tool.name, args });
49
62
  try {
50
63
  // Get user context (cached)
51
64
  const userContext = await UserContextCache_1.UserContextCache.getContext(apiKey);
52
65
  // Execute the tool
53
- const result = await toolRegistry.executeTool(toolDef.name, args, userContext);
66
+ const result = await toolRegistry.executeTool(tool.name, args, userContext);
54
67
  const duration = Date.now() - startTime;
55
- logger.info('Tool call completed', { toolName: toolDef.name, duration });
68
+ logger.info('Tool call completed', { toolName: tool.name, duration });
56
69
  // Handle different result formats
57
70
  if (result && typeof result === 'object' && 'content' in result) {
58
71
  // Result is already in MCP format { content: [...] }
@@ -69,7 +82,7 @@ async function startStdioServer(toolRegistry) {
69
82
  catch (error) {
70
83
  const duration = Date.now() - startTime;
71
84
  const errorMessage = error instanceof Error ? error.message : String(error);
72
- logger.error('Tool call failed', error, { toolName: toolDef.name, duration });
85
+ logger.error('Tool call failed', error, { toolName: tool.name, duration });
73
86
  return {
74
87
  content: [{
75
88
  type: 'text',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hailer/mcp",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "config": {
5
5
  "docker": {
6
6
  "registry": "registry.gitlab.com/hailer-repos/hailer-mcp"
@@ -28,6 +28,7 @@
28
28
  "dependencies": {
29
29
  "@anthropic-ai/sdk": "^0.54.0",
30
30
  "@hailer/cli": "^1.1.10",
31
+ "@hailer/mcp": "^1.0.24",
31
32
  "@modelcontextprotocol/sdk": "^1.11.5",
32
33
  "@opentelemetry/api-logs": "^0.57.0",
33
34
  "@opentelemetry/exporter-logs-otlp-proto": "^0.57.0",