Help us improve
Share bugs, ideas, or general feedback.
From claude-agent-sdk
Configures tool permissions, custom tools, and MCP servers in Claude Agent SDK using TypeScript. For building AI agents with file ops, bash, and external protocols.
npx claudepluginhub thebushidocollective/han --plugin claude-agent-sdkHow this skill is triggered — by the user, by Claude, or both
Slash command
/claude-agent-sdk:tool-integrationThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Working with tools, permissions, and MCP (Model Context Protocol) servers in the Claude Agent SDK.
Creates and configures Claude AI agents using the Agent SDK in TypeScript. Covers initialization, system prompts, tool permissions, directory structure, and multi-provider authentication.
Configures tool permissions for Claude Code agents via --allowedTools flags, path patterns for file access, and Bash command prefixes. Reference for secure launches.
Implements hooks for permission control, blocking dangerous operations, and audit trails in custom Claude Code agents.
Share bugs, ideas, or general feedback.
Working with tools, permissions, and MCP (Model Context Protocol) servers in the Claude Agent SDK.
import { Agent } from '@anthropic-ai/claude-agent-sdk';
const agent = new Agent({
allowedTools: [
'read_file',
'write_file',
'list_files',
'grep',
'bash',
],
});
const agent = new Agent({
disallowedTools: ['bash', 'web_search'],
});
// Strict mode - requires explicit user approval
const agent = new Agent({
permissionMode: 'strict',
});
// Permissive mode - auto-approves known safe operations
const agent = new Agent({
permissionMode: 'permissive',
});
import { Agent, Tool } from '@anthropic-ai/claude-agent-sdk';
const customTool: Tool = {
name: 'get_weather',
description: 'Get current weather for a location',
input_schema: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'City name',
},
},
required: ['location'],
},
execute: async (input) => {
const { location } = input;
// Call weather API
return {
location,
temperature: 72,
conditions: 'sunny',
};
},
};
const agent = new Agent({
tools: [customTool],
});
const customTool: Tool = {
name: 'read_database',
description: 'Query the database',
input_schema: {
type: 'object',
properties: {
query: { type: 'string' },
},
required: ['query'],
},
execute: async (input, context) => {
// Context provides agent state and utilities
console.log('Agent model:', context.model);
const result = await runQuery(input.query);
return result;
},
};
const agent = new Agent({
mcpServers: {
filesystem: {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', '/path/to/allowed'],
},
git: {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-git'],
},
},
});
// Agent automatically has access to MCP server resources
const agent = new Agent({
mcpServers: {
filesystem: {
command: 'npx',
args: ['-y', '@modelcontextprotocol/server-filesystem', './data'],
},
},
});
// Agent can now read files via MCP
await agent.chat('Read the contents of data/config.json');
const agent = new Agent({
mcpServers: {
database: {
command: 'node',
args: ['./mcp-servers/database.js'],
env: {
DATABASE_URL: process.env.DATABASE_URL,
},
},
},
});
const response = await agent.chat('List all files in src/');
for await (const chunk of response) {
if (chunk.type === 'tool_use') {
console.log('Tool called:', chunk.name);
}
if (chunk.type === 'tool_result') {
console.log('Tool result:', chunk.content);
}
}
const customTool: Tool = {
name: 'risky_operation',
description: 'Perform risky operation',
input_schema: {
type: 'object',
properties: {
action: { type: 'string' },
},
required: ['action'],
},
execute: async (input) => {
try {
const result = await performOperation(input.action);
return { success: true, result };
} catch (error) {
return {
success: false,
error: error instanceof Error ? error.message : 'Unknown error',
};
}
},
};
// Good: Only allow necessary tools
const agent = new Agent({
allowedTools: ['read_file', 'list_files'],
});
// Avoid: Allowing all tools unnecessarily
const agent = new Agent({
allowedTools: ['*'],
});
const customTool: Tool = {
name: 'delete_file',
description: 'Delete a file',
input_schema: {
type: 'object',
properties: {
path: { type: 'string' },
},
required: ['path'],
},
execute: async (input) => {
// Validate input
if (!input.path || input.path.includes('..')) {
throw new Error('Invalid file path');
}
// Prevent deleting critical files
if (input.path.startsWith('/etc') || input.path.startsWith('/sys')) {
throw new Error('Cannot delete system files');
}
await deleteFile(input.path);
return { deleted: input.path };
},
};
// Good: Restrict filesystem access to specific directory
const agent = new Agent({
mcpServers: {
filesystem: {
command: 'npx',
args: [
'-y',
'@modelcontextprotocol/server-filesystem',
'./workspace', // Sandboxed to workspace only
],
},
},
});
// Bad: Unrestricted bash access
const agent = new Agent({
allowedTools: ['bash'],
});
// Better: Use specific tools instead
const agent = new Agent({
allowedTools: ['read_file', 'write_file', 'list_files'],
});
// Bad: Silent failure
const customTool: Tool = {
execute: async (input) => {
try {
return await riskyOperation(input);
} catch {
return null; // Silent failure
}
},
};
// Good: Explicit error handling
const customTool: Tool = {
execute: async (input) => {
try {
return await riskyOperation(input);
} catch (error) {
return {
error: true,
message: error instanceof Error ? error.message : 'Operation failed',
};
}
},
};