Custom Tools

Dynamic Tools Overview

Dynamic tools let you extend Kyew with custom MCP tools. Turn API calls, data transforms, and workflows into reusable tools that Claude can invoke.


Tool Types

Kyew supports four types of custom tools:

TypeUse CaseExecution
HTTP ProxyCall external APIsMakes HTTP requests
TransformData manipulationJSONata expressions
CodeComplex logicJavaScript in sandbox
ChainMulti-step workflowsExecutes tools in sequence

HTTP Proxy Tools

Call external APIs with authentication:

create_dynamic_tool({
  name: "github_create_issue",
  description: "Create an issue in a GitHub repository",
  tool_type: "http_proxy",
  input_schema: {
    type: "object",
    properties: {
      owner: { type: "string" },
      repo: { type: "string" },
      title: { type: "string" },
      body: { type: "string" }
    },
    required: ["owner", "repo", "title"]
  },
  http_config: {
    method: "POST",
    url_template: "https://api.github.com/repos/{{owner}}/{{repo}}/issues",
    body_template: {
      title: "{{title}}",
      body: "{{body}}"
    },
    connection_id: "my-github-connection"
  }
})

See HTTP Proxy Tools for details.


Transform Tools

Manipulate data using JSONata expressions:

create_dynamic_tool({
  name: "extract_emails",
  description: "Extract email addresses from text",
  tool_type: "transform",
  input_schema: {
    type: "object",
    properties: {
      text: { type: "string" }
    },
    required: ["text"]
  },
  transform_config: {
    expression: "$match(input.text, /[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}/g)"
  }
})

See Transform Tools for details.


Code Tools

Run JavaScript in isolated containers:

create_code_tool({
  name: "calculate_stats",
  description: "Calculate statistical measures",
  runtime: "javascript",
  input_schema: {
    type: "object",
    properties: {
      numbers: { type: "array", items: { type: "number" } }
    },
    required: ["numbers"]
  },
  code: `
export default {
  async fetch(request) {
    const { numbers } = await request.json();
    const sum = numbers.reduce((a, b) => a + b, 0);
    return Response.json({
      sum,
      mean: sum / numbers.length,
      min: Math.min(...numbers),
      max: Math.max(...numbers)
    });
  }
}
  `
})

See Code Tools for details.


Chain Tools

Combine multiple tools into workflows:

create_dynamic_tool({
  name: "deploy_and_notify",
  description: "Deploy to Cloudflare and post to Slack",
  tool_type: "chain",
  input_schema: {
    type: "object",
    properties: {
      environment: { type: "string" }
    },
    required: ["environment"]
  },
  chain_config: {
    steps: [
      {
        tool_name: "cloudflare_deploy",
        input_mapping: { env: "{{environment}}" }
      },
      {
        tool_name: "slack_post",
        input_mapping: {
          channel: "#deployments",
          message: "Deployed to {{environment}}"
        }
      }
    ]
  }
})

See Chain Tools for details.


Managing Dynamic Tools

List Tools

"list my custom tools"
"list active http_proxy tools"

Get Details

"show details for tool github_create_issue"

Update Tools

"update tool github_create_issue to add labels support"

Delete Tools

"delete tool github_create_issue"

Test Tools

"test tool github_create_issue with owner='me' repo='test' title='Bug'"

Connections

HTTP proxy tools need connections for authentication:

create_connection({
  name: "my-github-connection",
  provider: "github",
  auth_type: "bearer",
  api_key_config: {
    key: "ghp_xxxxxxxxxxxx",
    header_name: "Authorization",
    prefix: "Bearer "
  }
})

Authentication Types

TypeUse Case
api_keyHeader or query param API keys
bearerBearer token authentication
basicUsername/password (base64)
oauth2OAuth 2.0 flows

Tool Status

Dynamic tools have three statuses:

  • draft: Created but not activated
  • active: Available for use
  • disabled: Temporarily turned off
// Activate immediately
create_dynamic_tool({ ..., activate: true })

// Or activate later
update_dynamic_tool({ tool_id: "...", status: "active" })

Input Schemas

All tools require an input schema defining expected parameters:

{
  "type": "object",
  "properties": {
    "query": {
      "type": "string",
      "description": "Search query"
    },
    "limit": {
      "type": "number",
      "description": "Max results",
      "default": 10
    }
  },
  "required": ["query"]
}

This schema:

  • Validates input before execution
  • Documents parameters for Claude
  • Enables better suggestions

Template Syntax

HTTP and chain tools use {{variable}} templating:

{
  "url_template": "https://api.example.com/users/{{userId}}",
  "body_template": {
    "name": "{{name}}",
    "email": "{{email}}"
  }
}

Nested access:

{{user.profile.name}}

Best Practices

Name Tools Clearly

# Good
github_create_issue
slack_post_message

# Avoid
doThing
myTool1

Write Descriptions

Good descriptions help Claude choose the right tool:

# Good
"Create a new issue in a GitHub repository with title and optional body"

# Avoid
"GitHub stuff"

Validate Early

Use input schemas to catch errors before execution.

Test Before Activating

Use test_dynamic_tool to verify behavior before making tools active.

Secure Credentials

Never hardcode secrets in templates. Use connections for all authentication.

Previous
User Approval