# AI custom tools

## Get AI Custom Tool Guide

`TOOL discourse_ai_get_custom_tool_guide`

Retrieve one focused MiniRacer authoring topic. Usually pass only topic. preset_id is optional and used only with topic=presets to load one live example; extra preset_id values on other topics are ignored. Requires admin credentials.

Authentication: no security requirement declared for this operation.

Parameters:

- `topic` (argument, string, optional) - Focused guide section. Use presets to browse or retrieve live preset examples.
  Type: string
  
  Focused guide section. Use presets to browse or retrieve live preset examples.
  
  default: "overview"
  
  enum: ["overview","preamble","entrypoints","parameters","http","llm","rag","uploads","chain","secrets","discourse","context","crypto","limits","security","presets"]

- `preset_id` (argument, string, optional) - Optional live preset ID used only when topic=presets; ignored for every other topic.
  Type: string
  
  Optional live preset ID used only when topic=presets; ignored for every other topic.
  
  minLength: 1

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_get_custom_tool_guide",
    "arguments": {
        "topic": "overview",
        "preset_id": "string"
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_get_custom_tool_guide",
  "arguments": {
    "topic": "overview",
    "preset_id": "string"
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_get_custom_tool_guide", arguments={
  "topic": "overview",
  "preset_id": "string"
})
```


## List AI Custom Tools

`TOOL discourse_ai_list_custom_tools`

List concise database-backed custom-tool summaries and compact live preset metadata. Scripts, bindings, verbose parameter descriptions, and full records are omitted; use discourse_ai_get_custom_tool or the guide's preset lookup to zoom in. Requires admin credentials.

Authentication: no security requirement declared for this operation.

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_list_custom_tools",
    "arguments": {}
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_list_custom_tools",
  "arguments": {}
});
```

### Python

```python
result = await session.call_tool("discourse_ai_list_custom_tools", arguments={})
```


## Get AI Custom Tool

`TOOL discourse_ai_get_custom_tool`

Get one database-backed scripted AI tool, including source and configured secret bindings. Treat the response as sensitive. Requires admin credentials.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `id` (required)
  Type: integer | string
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: string
    
    pattern: "^\\d+$"

Additional properties: false

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_get_custom_tool",
    "arguments": {
        "id": 0
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_get_custom_tool",
  "arguments": {
    "id": 0
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_get_custom_tool", arguments={
  "id": 0
})
```


## Create AI Custom Tool

`TOOL discourse_ai_create_custom_tool`

Create a database-backed synchronous MiniRacer scripted tool. Call discourse_ai_get_custom_tool_guide before authoring. Never provide raw secret values. Requires admin credentials and write mode.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `name` (required)
  Type: string
  
  minLength: 1

- `tool_name` (required)
  Type: string
  
  minLength: 1
  
  pattern: "^[a-zA-Z0-9_-]+$"

- `description` (required)
  Type: string
  
  minLength: 1

- `summary` (required)
  Type: string
  
  minLength: 1

- `script` (required)
  Type: string
  
  minLength: 1
  
  maxLength: 100000

- `parameters` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `name` (required)
      Type: string
      
      minLength: 1
    
    - `type` (required)
      Type: string
      
      enum: ["string","number","boolean","array"]
    
    - `description` (required)
      Type: string
      
      minLength: 1
    
    - `required` (required)
      Type: boolean
    
    - `enum` (optional)
      Type: Array<string | number>
      
      minItems: 1
      
      Items:
        Type: string | number
    
    Additional properties: false

- `secret_contracts` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `alias` (required)
      Type: string
      
      minLength: 1
    
    Additional properties: false

- `secret_bindings` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `alias` (required)
      Type: string
      
      minLength: 1
    
    - `ai_secret_id` (required)
      Type: integer | null
      
      anyOf:
        Type: integer
        
        exclusiveMinimum: 0
      
        Type: null
    
    Additional properties: false

- `rag_chunk_tokens` (optional)
  Type: integer
  
  minimum: 1
  
  maximum: 50000

- `rag_chunk_overlap_tokens` (optional)
  Type: integer
  
  minimum: 0
  
  maximum: 200

- `rag_llm_model_id` (optional)
  Type: integer | null
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: null

- `rag_uploads` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `id` (required)
      Type: integer
      
      exclusiveMinimum: 0
    
    Additional properties: false

Additional properties: false

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_create_custom_tool",
    "arguments": {
        "name": "string",
        "tool_name": "string",
        "description": "string",
        "summary": "string",
        "script": "string",
        "parameters": [
          {
            "name": "string",
            "type": "string",
            "description": "string",
            "required": true,
            "enum": [
              "string"
            ]
          }
        ],
        "secret_contracts": [
          {
            "alias": "string"
          }
        ],
        "secret_bindings": [
          {
            "alias": "string",
            "ai_secret_id": 0
          }
        ],
        "rag_chunk_tokens": 1,
        "rag_chunk_overlap_tokens": 0,
        "rag_llm_model_id": 0,
        "rag_uploads": [
          {
            "id": 0
          }
        ]
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_create_custom_tool",
  "arguments": {
    "name": "string",
    "tool_name": "string",
    "description": "string",
    "summary": "string",
    "script": "string",
    "parameters": [
      {
        "name": "string",
        "type": "string",
        "description": "string",
        "required": true,
        "enum": [
          "string"
        ]
      }
    ],
    "secret_contracts": [
      {
        "alias": "string"
      }
    ],
    "secret_bindings": [
      {
        "alias": "string",
        "ai_secret_id": 0
      }
    ],
    "rag_chunk_tokens": 1,
    "rag_chunk_overlap_tokens": 0,
    "rag_llm_model_id": 0,
    "rag_uploads": [
      {
        "id": 0
      }
    ]
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_create_custom_tool", arguments={
  "name": "string",
  "tool_name": "string",
  "description": "string",
  "summary": "string",
  "script": "string",
  "parameters": [
    {
      "name": "string",
      "type": "string",
      "description": "string",
      "required": true,
      "enum": [
        "string"
      ]
    }
  ],
  "secret_contracts": [
    {
      "alias": "string"
    }
  ],
  "secret_bindings": [
    {
      "alias": "string",
      "ai_secret_id": 0
    }
  ],
  "rag_chunk_tokens": 1,
  "rag_chunk_overlap_tokens": 0,
  "rag_llm_model_id": 0,
  "rag_uploads": [
    {
      "id": 0
    }
  ]
})
```


## Update AI Custom Tool

`TOOL discourse_ai_update_custom_tool`

Partially update a scripted tool. Call the guide before substantial script changes. Omitted scalar fields and RAG uploads are preserved; changing secret_contracts can prune orphan bindings unless secret_bindings are supplied. Raw secret values are never accepted. Requires admin credentials and write mode.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `id` (required)
  Type: integer | string
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: string
    
    pattern: "^\\d+$"

- `name` (optional)
  Type: string
  
  minLength: 1

- `tool_name` (optional)
  Type: string
  
  minLength: 1
  
  pattern: "^[a-zA-Z0-9_-]+$"

- `description` (optional)
  Type: string
  
  minLength: 1

- `summary` (optional)
  Type: string
  
  minLength: 1

- `script` (optional)
  Type: string
  
  minLength: 1
  
  maxLength: 100000

- `parameters` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `name` (required)
      Type: string
      
      minLength: 1
    
    - `type` (required)
      Type: string
      
      enum: ["string","number","boolean","array"]
    
    - `description` (required)
      Type: string
      
      minLength: 1
    
    - `required` (required)
      Type: boolean
    
    - `enum` (optional)
      Type: Array<string | number>
      
      minItems: 1
      
      Items:
        Type: string | number
    
    Additional properties: false

- `secret_contracts` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `alias` (required)
      Type: string
      
      minLength: 1
    
    Additional properties: false

- `secret_bindings` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `alias` (required)
      Type: string
      
      minLength: 1
    
    - `ai_secret_id` (required)
      Type: integer | null
      
      anyOf:
        Type: integer
        
        exclusiveMinimum: 0
      
        Type: null
    
    Additional properties: false

- `rag_chunk_tokens` (optional)
  Type: integer
  
  minimum: 1
  
  maximum: 50000

- `rag_chunk_overlap_tokens` (optional)
  Type: integer
  
  minimum: 0
  
  maximum: 200

- `rag_llm_model_id` (optional)
  Type: integer | null
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: null

- `rag_uploads` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `id` (required)
      Type: integer
      
      exclusiveMinimum: 0
    
    Additional properties: false

Additional properties: false

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_update_custom_tool",
    "arguments": {
        "id": 0,
        "name": "string",
        "tool_name": "string",
        "description": "string",
        "summary": "string",
        "script": "string",
        "parameters": [
          {
            "name": "string",
            "type": "string",
            "description": "string",
            "required": true,
            "enum": [
              "string"
            ]
          }
        ],
        "secret_contracts": [
          {
            "alias": "string"
          }
        ],
        "secret_bindings": [
          {
            "alias": "string",
            "ai_secret_id": 0
          }
        ],
        "rag_chunk_tokens": 1,
        "rag_chunk_overlap_tokens": 0,
        "rag_llm_model_id": 0,
        "rag_uploads": [
          {
            "id": 0
          }
        ]
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_update_custom_tool",
  "arguments": {
    "id": 0,
    "name": "string",
    "tool_name": "string",
    "description": "string",
    "summary": "string",
    "script": "string",
    "parameters": [
      {
        "name": "string",
        "type": "string",
        "description": "string",
        "required": true,
        "enum": [
          "string"
        ]
      }
    ],
    "secret_contracts": [
      {
        "alias": "string"
      }
    ],
    "secret_bindings": [
      {
        "alias": "string",
        "ai_secret_id": 0
      }
    ],
    "rag_chunk_tokens": 1,
    "rag_chunk_overlap_tokens": 0,
    "rag_llm_model_id": 0,
    "rag_uploads": [
      {
        "id": 0
      }
    ]
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_update_custom_tool", arguments={
  "id": 0,
  "name": "string",
  "tool_name": "string",
  "description": "string",
  "summary": "string",
  "script": "string",
  "parameters": [
    {
      "name": "string",
      "type": "string",
      "description": "string",
      "required": true,
      "enum": [
        "string"
      ]
    }
  ],
  "secret_contracts": [
    {
      "alias": "string"
    }
  ],
  "secret_bindings": [
    {
      "alias": "string",
      "ai_secret_id": 0
    }
  ],
  "rag_chunk_tokens": 1,
  "rag_chunk_overlap_tokens": 0,
  "rag_llm_model_id": 0,
  "rag_uploads": [
    {
      "id": 0
    }
  ]
})
```


## Delete AI Custom Tool

`TOOL discourse_ai_delete_custom_tool`

Delete a scripted tool. Agents referencing it may stop functioning as configured. Requires admin credentials and write mode.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `id` (required)
  Type: integer | string
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: string
    
    pattern: "^\\d+$"

Additional properties: false

Declared MCP annotations:

```json
{
  "destructiveHint": true
}
```

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_delete_custom_tool",
    "arguments": {
        "id": 0
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_delete_custom_tool",
  "arguments": {
    "id": 0
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_delete_custom_tool", arguments={
  "id": 0
})
```


## Test AI Custom Tool

`TOOL discourse_ai_test_custom_tool`

Actually execute a persisted or unsaved custom-tool script. It can make external requests and cause side effects; this is not dry validation. Requires admin credentials and write mode.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `id` (required)
  Type: integer | string
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: string
    
    pattern: "^\\d+$"

- `parameters` (optional)
  Type: object
  
  default: {}
  
  Additional properties: 
    Type: any

- `script` (optional)
  Type: string
  
  minLength: 1
  
  maxLength: 100000

- `secret_bindings` (optional)
  Type: Array<object>
  
  Items:
    Type: object
    
    - `alias` (required)
      Type: string
      
      minLength: 1
    
    - `ai_secret_id` (required)
      Type: integer | null
      
      anyOf:
        Type: integer
        
        exclusiveMinimum: 0
      
        Type: null
    
    Additional properties: false

Additional properties: false

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_test_custom_tool",
    "arguments": {
        "id": 0,
        "parameters": {},
        "script": "string",
        "secret_bindings": [
          {
            "alias": "string",
            "ai_secret_id": 0
          }
        ]
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_test_custom_tool",
  "arguments": {
    "id": 0,
    "parameters": {},
    "script": "string",
    "secret_bindings": [
      {
        "alias": "string",
        "ai_secret_id": 0
      }
    ]
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_test_custom_tool", arguments={
  "id": 0,
  "parameters": {},
  "script": "string",
  "secret_bindings": [
    {
      "alias": "string",
      "ai_secret_id": 0
    }
  ]
})
```


## Export AI Custom Tool

`TOOL discourse_ai_export_custom_tool`

Export portable custom-tool JSON. Discourse excludes secret bindings; MCP also strips them defensively. Treat script source as sensitive. Requires admin credentials.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `id` (required)
  Type: integer | string
  
  anyOf:
    Type: integer
    
    exclusiveMinimum: 0
  
    Type: string
    
    pattern: "^\\d+$"

Additional properties: false

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_export_custom_tool",
    "arguments": {
        "id": 0
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_export_custom_tool",
  "arguments": {
    "id": 0
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_export_custom_tool", arguments={
  "id": 0
})
```


## Import AI Custom Tool

`TOOL discourse_ai_import_custom_tool`

Import portable custom-tool JSON. force overwrites a matching tool_name and requires confirm_force=true. Secret IDs may be bound, but raw secret values are never accepted. Requires admin credentials and write mode.

Authentication: no security requirement declared for this operation.

Request body: application/json (required)

Type: object

- `ai_tool` (required)
  Type: object
  
  - `name` (required)
    Type: string
    
    minLength: 1
  
  - `tool_name` (required)
    Type: string
    
    minLength: 1
    
    pattern: "^[a-zA-Z0-9_-]+$"
  
  - `description` (required)
    Type: string
    
    minLength: 1
  
  - `summary` (required)
    Type: string
    
    minLength: 1
  
  - `script` (required)
    Type: string
    
    minLength: 1
    
    maxLength: 100000
  
  - `parameters` (optional)
    Type: Array<object>
    
    Items:
      Type: object
      
      - `name` (required)
        Type: string
        
        minLength: 1
      
      - `type` (required)
        Type: string
        
        enum: ["string","number","boolean","array"]
      
      - `description` (required)
        Type: string
        
        minLength: 1
      
      - `required` (required)
        Type: boolean
      
      - `enum` (optional)
        Type: Array<string | number>
        
        minItems: 1
        
        Items:
          Type: string | number
      
      Additional properties: false
  
  - `secret_contracts` (optional)
    Type: Array<object>
    
    Items:
      Type: object
      
      - `alias` (required)
        Type: string
        
        minLength: 1
      
      Additional properties: false
  
  - `secret_bindings` (optional)
    Type: Array<object>
    
    Items:
      Type: object
      
      - `alias` (required)
        Type: string
        
        minLength: 1
      
      - `ai_secret_id` (required)
        Type: integer | null
        
        anyOf:
          Type: integer
          
          exclusiveMinimum: 0
        
          Type: null
      
      Additional properties: false
  
  - `rag_chunk_tokens` (optional)
    Type: integer
    
    minimum: 1
    
    maximum: 50000
  
  - `rag_chunk_overlap_tokens` (optional)
    Type: integer
    
    minimum: 0
    
    maximum: 200
  
  - `rag_llm_model_id` (optional)
    Type: integer | null
    
    anyOf:
      Type: integer
      
      exclusiveMinimum: 0
    
      Type: null
  
  - `rag_uploads` (optional)
    Type: Array<object>
    
    Items:
      Type: object
      
      - `id` (required)
        Type: integer
        
        exclusiveMinimum: 0
      
      Additional properties: false
  
  - `id` (optional)
    Type: integer
    
    exclusiveMinimum: 0
  
  - `created_by_id` (optional)
    Type: integer
    
    exclusiveMinimum: 0
  
  - `created_at` (optional)
    Type: string
  
  - `updated_at` (optional)
    Type: string
  
  Additional properties: false

- `force` (optional)
  Type: boolean
  
  default: false

- `confirm_force` (optional)
  Type: boolean
  
  default: false

Additional properties: false

Declared MCP annotations:

```json
{
  "destructiveHint": true
}
```

## Examples

### JSON-RPC

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "discourse_ai_import_custom_tool",
    "arguments": {
        "ai_tool": {
          "name": "string",
          "tool_name": "string",
          "description": "string",
          "summary": "string",
          "script": "string",
          "parameters": [
            {
              "name": "string",
              "type": "string",
              "description": "string",
              "required": true,
              "enum": [
                "string"
              ]
            }
          ],
          "secret_contracts": [
            {
              "alias": "string"
            }
          ],
          "secret_bindings": [
            {
              "alias": "string",
              "ai_secret_id": 0
            }
          ],
          "rag_chunk_tokens": 1,
          "rag_chunk_overlap_tokens": 0,
          "rag_llm_model_id": 0,
          "rag_uploads": [
            {
              "id": 0
            }
          ],
          "id": 0,
          "created_by_id": 0,
          "created_at": "string",
          "updated_at": "string"
        },
        "force": false,
        "confirm_force": false
      }
  }
}
```

### TypeScript

```typescript
const result = await client.callTool({
  "name": "discourse_ai_import_custom_tool",
  "arguments": {
    "ai_tool": {
      "name": "string",
      "tool_name": "string",
      "description": "string",
      "summary": "string",
      "script": "string",
      "parameters": [
        {
          "name": "string",
          "type": "string",
          "description": "string",
          "required": true,
          "enum": [
            "string"
          ]
        }
      ],
      "secret_contracts": [
        {
          "alias": "string"
        }
      ],
      "secret_bindings": [
        {
          "alias": "string",
          "ai_secret_id": 0
        }
      ],
      "rag_chunk_tokens": 1,
      "rag_chunk_overlap_tokens": 0,
      "rag_llm_model_id": 0,
      "rag_uploads": [
        {
          "id": 0
        }
      ],
      "id": 0,
      "created_by_id": 0,
      "created_at": "string",
      "updated_at": "string"
    },
    "force": false,
    "confirm_force": false
  }
});
```

### Python

```python
result = await session.call_tool("discourse_ai_import_custom_tool", arguments={
  "ai_tool": {
    "name": "string",
    "tool_name": "string",
    "description": "string",
    "summary": "string",
    "script": "string",
    "parameters": [
      {
        "name": "string",
        "type": "string",
        "description": "string",
        "required": true,
        "enum": [
          "string"
        ]
      }
    ],
    "secret_contracts": [
      {
        "alias": "string"
      }
    ],
    "secret_bindings": [
      {
        "alias": "string",
        "ai_secret_id": 0
      }
    ],
    "rag_chunk_tokens": 1,
    "rag_chunk_overlap_tokens": 0,
    "rag_llm_model_id": 0,
    "rag_uploads": [
      {
        "id": 0
      }
    ],
    "id": 0,
    "created_by_id": 0,
    "created_at": "string",
    "updated_at": "string"
  },
  "force": false,
  "confirm_force": false
})
```
