Skip to content

Commit 0104868

Browse files
committed
feat(tool): add toClaudeAgentSdk() method to Tools class
Add toClaudeAgentSdk() method that converts all tools in a collection to Claude Agent SDK format, automatically creating an MCP server. This simplifies integration with Claude Agent SDK from requiring manual Zod schema definitions and MCP server setup to a single method call. The method: - Converts JSON Schema parameters to Zod schemas dynamically - Creates Claude Agent SDK tool definitions with handlers - Wraps tools in an MCP server via createSdkMcpServer() - Supports configurable server name and version Also adds toClaudeAgentSdkTool() helper method on BaseTool for converting individual tools.
1 parent b34af20 commit 0104868

File tree

1 file changed

+90
-0
lines changed

1 file changed

+90
-0
lines changed

src/tool.ts

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { RequestBuilder } from './requestBuilder';
1010
import type {
1111
AISDKToolDefinition,
1212
AISDKToolResult,
13+
ClaudeAgentSdkMcpServer,
14+
ClaudeAgentSdkOptions,
1315
ExecuteConfig,
1416
ExecuteOptions,
1517
HttpExecuteConfig,
@@ -22,6 +24,7 @@ import type {
2224
} from './types';
2325

2426
import { StackOneError } from './utils/error-stackone';
27+
import { jsonSchemaToZod } from './utils/json-schema-to-zod';
2528
import { TfidfIndex } from './utils/tfidf-index';
2629
import { tryImport } from './utils/try-import';
2730

@@ -225,6 +228,36 @@ export class BaseTool {
225228
};
226229
}
227230

231+
/**
232+
* Convert the tool to Claude Agent SDK format.
233+
* Returns a tool definition compatible with the Claude Agent SDK's tool() function.
234+
*
235+
* @see https://docs.anthropic.com/en/docs/agents-and-tools/claude-agent-sdk
236+
*/
237+
async toClaudeAgentSdkTool(): Promise<{
238+
name: string;
239+
description: string;
240+
inputSchema: Record<string, unknown>;
241+
handler: (
242+
args: Record<string, unknown>,
243+
) => Promise<{ content: Array<{ type: 'text'; text: string }> }>;
244+
}> {
245+
const { zodSchema } = await jsonSchemaToZod(this.toJsonSchema());
246+
const execute = this.execute.bind(this);
247+
248+
return {
249+
name: this.name,
250+
description: this.description,
251+
inputSchema: zodSchema,
252+
handler: async (args: Record<string, unknown>) => {
253+
const result = await execute(args as JsonObject);
254+
return {
255+
content: [{ type: 'text' as const, text: JSON.stringify(result) }],
256+
};
257+
},
258+
};
259+
}
260+
228261
/**
229262
* Convert the tool to AI SDK format
230263
*/
@@ -395,6 +428,63 @@ export class Tools implements Iterable<BaseTool> {
395428
return result;
396429
}
397430

431+
/**
432+
* Convert all tools to Claude Agent SDK format.
433+
* Returns an MCP server configuration that can be passed to the
434+
* Claude Agent SDK query() function's mcpServers option.
435+
*
436+
* @example
437+
* ```typescript
438+
* const tools = await toolset.fetchTools();
439+
* const mcpServer = await tools.toClaudeAgentSdk();
440+
*
441+
* const result = query({
442+
* prompt: 'Get employee info',
443+
* options: {
444+
* model: 'claude-sonnet-4-5-20250929',
445+
* mcpServers: {
446+
* 'stackone-tools': mcpServer,
447+
* },
448+
* },
449+
* });
450+
* ```
451+
*
452+
* @see https://docs.anthropic.com/en/docs/agents-and-tools/claude-agent-sdk
453+
*/
454+
async toClaudeAgentSdk(options: ClaudeAgentSdkOptions = {}): Promise<ClaudeAgentSdkMcpServer> {
455+
const { serverName = 'stackone-tools', serverVersion = '1.0.0' } = options;
456+
457+
// Import the Claude Agent SDK dynamically
458+
const claudeAgentSdk = await tryImport<typeof import('@anthropic-ai/claude-agent-sdk')>(
459+
'@anthropic-ai/claude-agent-sdk',
460+
`npm install @anthropic-ai/claude-agent-sdk (requires ${peerDependencies['@anthropic-ai/claude-agent-sdk']})`,
461+
);
462+
463+
// Convert all tools to Claude Agent SDK format
464+
// We use type assertions here because the Zod types from our dynamic import
465+
// don't perfectly match the Claude Agent SDK's expected types at compile time
466+
const sdkTools = await Promise.all(
467+
this.tools.map(async (baseTool) => {
468+
const toolDef = await baseTool.toClaudeAgentSdkTool();
469+
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Dynamic Zod schema types
470+
return claudeAgentSdk.tool(
471+
toolDef.name,
472+
toolDef.description,
473+
toolDef.inputSchema as any,
474+
toolDef.handler as any,
475+
);
476+
}),
477+
);
478+
479+
// Create and return the MCP server
480+
// The return type is compatible with McpServerConfig but uses our interface
481+
return claudeAgentSdk.createSdkMcpServer({
482+
name: serverName,
483+
version: serverVersion,
484+
tools: sdkTools,
485+
}) as ClaudeAgentSdkMcpServer;
486+
}
487+
398488
/**
399489
* Filter tools by a predicate function
400490
*/

0 commit comments

Comments
 (0)