> ## Documentation Index
> Fetch the complete documentation index at: https://docs.typingmind.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugin JSON Schema

## Overview

TypingMind plugin can be completely described using a JSON object. Below is the description of each feature of the plugin and their corresponding JSON schema.

Plugin name, title, icon, overview, GitHub source URL, and authentication type, and permissions are defined as the following example:

```json theme={null}
{
    "id": "f1af15c3-23ba-4548-a123-ea72d9a70dfd",
    "uuid": "f1af15c3-23ba-4548-a123-ea72d9a70dfd",
    "title": "Web Search (Serp)",
    "iconURL": "https://raw.githubusercontent.com/TypingMind/plugin-web-search-serp/refs/heads/main/icon.webp",
    "createdAt": "2025-09-12T05:36:39.890Z",
    "githubURL": "https://github.com/TypingMind/plugin-web-search-serp",
    "overviewMarkdown": "## Web Search (SerpApi)\n\nThis plugin allows the AI assistant to search for information from the internet in real-time using Google Search.\n\n**🔑 Serp API Key needed**. Click the Settings tab and enter your Serp API Key. To get your API Key, [create a Serp account](https://serpapi.com/)\n\nExample usage:\n\n> What's the gold price today?\n\n> How's the weather in SF at the moment?\n",
    "authenticationType": "AUTH_TYPE_NONE",
    "permissions": [
        "read_user_message"
    ],
}
```

You can use these values in `permissions`:

* `read_user_message`: read the latest user message and its attachments.
* `read_chat_attachments`: read the chat files that the AI sends in [`typingmind-attachment` parameters](#chat-file-parameters).

User settings example:

```json theme={null}
{
  "userSettings": [
    [
      {
        "name": "searchServiceName",
        "label": "Search Service Name",
        "description": "Find this in the \"Azure AI Services\" section in the Azure portal.",
        "required": true
      },
      {
        "name": "indexName",
        "label": "Index Name",
        "description": "Find this in \"Search managements\" → \"Indexes\" page in the Azure portal.",
        "required": true
      },
      {
        "name": "queryKey",
        "type": "password",
        "label": "Query Key",
        "description": "Find this in \"Settings\" → \"Keys\" page in the Azure portal.",
        "required": true
      },
      {
        "name": "apiVersion",
        "label": "API Version",
        "required": true,
        "description": "Find the latest API version here: https://learn.microsoft.com/en-us/rest/api/searchservice/search-service-api-versions",
        "defaultValue": "2023-11-01"
      }
    ]
  ]
}
```

Plugin context example:

```json theme={null}
{
    "dynamicContextEndpoints": [
        {
            "id": "936cf499-0126-405f-b753-9cb9b553633a",
            "url": "",
            "name": "How to use this plugin",
            "method": "GET",
            "source": "static",
            "staticContent": "Activate this plugin when the user mention their pet.",
            "cacheDurationHours": 1,
            "cacheRefreshPolicy": "REFRESH_NEVER"
        },
        {
            "id": "9320d905-2ed0-4612-abcd-94c811a22f7f",
            "url": "https://www.typingmind.com/api/version",
            "name": "Latest version",
            "method": "GET",
            "cacheDurationHours": 1,
            "cacheRefreshPolicy": "REFRESH_NEVER"
        },
        {
            "id": "c81b6cf5-9045-4b41-9111-0def64b657bd",
            "name": "Retrieve index",
            "url": "https://test.com/index-endpoint",
            "source": "http",
            "method": "POST",
            "cacheRefreshPolicy": "REFRESH_NEVER",
            "cacheDurationHours": 1,
            "hasBody": true,
            "enableCache": false,
            "hasHeaders": true,
            "requestBody": "{\n  \"Authorization\": \"Bearer {OAUTH_PLUGIN_ACCESS_TOKEN}\"\n}",
            "requestHeaders": "{\n  \"chatID\": \"{chatID}\"\n}"
        }
    ],
}
```

OAuth config example:

```json theme={null}
{
    "oauthConfig": {
        "prompt": "",
        "scopes": "chat:write",
        "tokenURL": "https://slack.com/api/oauth.v2.access",
        "accessType": "offline",
        "contentType": "urlencoded",
        "authorizationURL": "https://slack.com/oauth/v2/authorize"
    }
}
```

Plugin functions is defined as an array of multiple function.

Here is an example for a function with HTTP Action implementation type.

```json theme={null}
{
  "pluginFunctions": [
    {
      "id": "430f1bac-9335-450a-ba87-3a1de1a1515c",
      "code": "",
      "name": "send_message_to_slack_channel_via_http_action",
      "httpAction": {
        "id": "4f777638-cdbd-4807-9044-6c4a261ecd7c",
        "url": "https://slack.com/api/chat.postMessage",
        "name": "",
        "method": "POST",
        "hasBody": true,
        "hasHeaders": true,
        "requestBody": "{\n  \"channel\": \"{channel}\",\n  \"text\": \"{message}\"\n}",
        "requestHeaders": "{\n  \"Authorization\": \"Bearer {OAUTH_PLUGIN_ACCESS_TOKEN}\"\n}",
        "requestBodyFormat": "form-data"
      },
      "openaiSpec": {
        "name": "send_message_to_slack_channel_via_http_action",
        "parameters": {
          "type": "object",
          "required": [
            "channel",
            "message"
          ],
          "properties": {
            "channel": {
              "type": "string",
              "description": "This parameter specifies the target Slack channel name."
            },
            "message": {
              "type": "string",
              "description": "This parameter specifies the message a user wants to send to the Slack channel."
            }
          }
        },
        "description": "This function sends an authorized user's message to a specific Slack channel via an HTTP action."
      },
      "outputType": "respond_to_ai",
      "implementationType": "http"
    }
  ]
}
```

Here is an example for a function with JavaScript implementation type.

```json theme={null}
{
  "pluginFunctions": [
    {
      "id": "44adfca5-44ad-4a4c-b224-5e476136665d",
      "name": "render_chart",
      "implementationType": "javascript",
      "openaiSpec": {
        "name": "render_chart",
        "parameters": {
          "type": "object",
          "required": [
            "title",
            "chartType",
            "data",
            "options"
          ],
          "properties": {
            "data": {
              "type": "object",
              "required": [
                "labels",
                "datasets"
              ],
              "properties": {
                "labels": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  },
                  "description": "Labels for the chart"
                },
                "datasets": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "required": [
                      "label",
                      "data"
                    ],
                    "properties": {
                      "data": {
                        "type": "array",
                        "items": {
                          "type": "number"
                        },
                        "description": "Data points for the dataset"
                      }
                    }
                  },
                  "description": "Datasets to be rendered in the chart"
                }
              },
              "description": "Data to be rendered in the chart"
            },
            "title": {
              "type": "string",
              "description": "The title of the chart"
            },
            "chartType": {
              "enum": [
                "line",
                "bar",
                "doughnut",
                "pie",
                "radar",
                "polarArea",
                "bubble",
                "scatter"
              ],
              "type": "string",
              "description": "Type of the chart to render"
            }
          }
        },
        "description": "Generate a Chart.js chart"
      },
      "code": "function render_chart(params) {\n    const { chartType, options, title, data } = params;\n    const dataString = JSON.stringify(data)\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/\"/g, '\\\\\"')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\r/g, '\\\\r')\n        .replace(/\\t/g, '\\\\t');\n\n    const optionsString = JSON.stringify(options)\n        .replace(/\\\\/g, '\\\\\\\\')\n        .replace(/\"/g, '\\\\\"')\n        .replace(/\\n/g, '\\\\n')\n        .replace(/\\r/g, '\\\\r')\n        .replace(/\\t/g, '\\\\t');\n\n    const htmlString = `\n    <!DOCTYPE html>\n    <html>\n    <head>\n        <title>${title}</title>\n        <script src=\"https://cdn.jsdelivr.net/npm/chart.js\"></script>\n    </head>\n    <body>\n        <canvas id=\"generated-chart\" style=\"width: 100%; height: 90vh;\"></canvas>\n        <script>\n            var ctx = document.getElementById('generated-chart').getContext('2d');\n            var chart = new Chart(ctx, {\n                type: '${chartType}',\n                data: JSON.parse(\"${dataString}\"),\n                options: JSON.parse(\"${optionsString}\")\n            });\n        </script>\n    </body>\n    </html>\n    `;\n    return htmlString;\n}\n",
      "outputType": "render_html"
    }
  ]
}
```

Here is an example for a function with MCP implementation type.

```json theme={null}
{
  "pluginFunctions": [
    {
      "id": "789803e1-8967-441d-b8df-17cbfd68f1d4",
      "code": "",
      "name": "Run browser",
        "id": "puppeteer_v2",
        "serverConfig": {
          "mcpServers": {
            "puppeteer_v2": {
              "args": [
                "-y",
                "@modelcontextprotocol/server-puppeteer",
                "{OAUTH_PLUGIN_ACCESS_TOKEN}",
                "{variableName1}",
                "{varibaleName2}"
              ],
              "command": "npx"
            }
          }
        }
      },
      "outputType": "respond_to_ai",
      "implementationType": "mcp"
    }
  ]
}
```

## Chat file parameters

A parameter of the type `typingmind-attachment` gets a file from the chat. An `array` of this type gets more than one file. If the plugin has the `read_chat_attachments` permission, the JavaScript function receives the files in `resources.attachments`.

```json theme={null}
{
  "permissions": ["read_chat_attachments"],
  "pluginFunctions": [
    {
      "id": "summarize-files",
      "name": "Summarize Files",
      "implementationType": "javascript",
      "openaiSpec": {
        "name": "summarize_files",
        "description": "Summarize one or more files from the chat.",
        "parameters": {
          "type": "object",
          "properties": {
            "files": {
              "type": "array",
              "items": { "type": "typingmind-attachment" },
              "description": "The files to summarize."
            }
          },
          "required": ["files"]
        }
      },
      "code": "async function summarize_files(params, userSettings, resources) {\n  return resources.attachments.map((file) => `${file.name} (${file.type}, ${file.size} bytes)`).join('\\n');\n}",
      "outputType": "respond_to_ai"
    }
  ]
}
```

For more information, refer to [Chat file parameters](/plugins/build-a-typingmind-plugin#chat-file-parameters).

## JavaScript source files

For plugins hosted on GitHub, a JavaScript entry in `pluginFunctions` can use `codeFile` instead of an inline `code` string. This keeps the implementation in a separate `.js` file.

`codeFile` is a path relative to the repository root, where `plugin.json` is stored. For example, `"codeFile": "functions/add-numbers.js"` loads that file from the same repository and branch as `plugin.json`.

Example function configuration in `plugin.json`:

```json theme={null}
{
  "pluginFunctions": [
    {
      "id": "add-numbers",
      "name": "Add Numbers",
      "implementationType": "javascript",
      "codeFile": "functions/add-numbers.js",
      "openaiSpec": {
        "name": "add_numbers",
        "description": "Add two numbers.",
        "parameters": {
          "type": "object",
          "properties": {
            "a": { "type": "number" },
            "b": { "type": "number" }
          },
          "required": ["a", "b"]
        }
      },
      "outputType": "respond_to_ai"
    }
  ]
}
```

Contents of `functions/add-numbers.js`:

```javascript theme={null}
function add_numbers({ a, b }) {
  return a + b;
}
```

The file must define a top-level function with the same name as `openaiSpec.name`.

* Use `codeFile` only in JavaScript entries in `pluginFunctions`. Set `"implementationType": "javascript"` in these entries.
* Existing inline `code` strings are still supported. If both `codeFile` and `code` are set, the file contents take precedence.
* TypingMind reads the file during GitHub import and stores its contents as `code`. The file is not fetched on each function call.
* Import fails if the referenced file cannot be fetched; it does not fall back to inline `code`.
* For standalone JSON imports or the JSON Editor, include the implementation in `code`. File references are resolved by the GitHub importer.

## Function execution and output settings

These fields belong to each function object in `pluginFunctions`:

| Field | Type | Default | Description |
| - | - | - | - |
| `networkAccess` | Boolean | `true` | JavaScript only. Set to `false` to apply the sandbox's network restrictions. Selected chat attachments are supplied as base64 data URLs. |
| `outputType` | String | `respond_to_ai` | Controls how TypingMind handles the function's return value. |

Supported output types:

| Value | Behavior |
| - | - |
| `respond_to_ai` | Give the return value to the AI. Objects and arrays are serialized as JSON text. |
| `content_blocks` | Accept `{ "content": [...] }`, send text blocks to the AI, and save embedded resources as chat attachments. |
| `render_markdown` | Render the result as Markdown. |
| `render_html` | Render the result as interactive HTML. |
| `cards` | Render TypingMind Cards. |

For `content_blocks`, each embedded resource includes a filename URI and either literal `text` or base64 `blob` contents. See [Give text and files to the AI](/plugins/build-a-typingmind-plugin#give-text-and-files-to-the-ai) for the return format and binary-file examples.

This example defines an offline JavaScript function that creates a text attachment:

```json theme={null}
{
  "pluginFunctions": [
    {
      "id": "create-notes",
      "name": "Create notes",
      "implementationType": "javascript",
      "networkAccess": false,
      "outputType": "content_blocks",
      "openaiSpec": {
        "name": "create_notes",
        "description": "Create a text file containing the supplied notes.",
        "parameters": {
          "type": "object",
          "properties": {
            "task_description": {
              "type": "string",
              "description": "Describe this task in 5 words or fewer, in the user's language."
            },
            "text": {
              "type": "string",
              "description": "The complete text to save in notes.txt."
            }
          },
          "required": ["task_description", "text"]
        }
      },
      "code": "function create_notes({ text }) { return { content: [{ type: 'resource', resource: { uri: 'file:///notes.txt', mimeType: 'text/plain', text } }] }; }"
    }
  ]
}
```

`task_description` is a function parameter supplied by the AI. TypingMind displays it in the active activity group header and the tool call row. It is separate from the function-level `networkAccess` and `outputType` settings.

To read files already in the conversation, add `read_chat_attachments` to the plugin's `permissions` and declare attachment parameters with the `typingmind-attachment` type. See [Chat file parameters](#chat-file-parameters).

## Complete example

Below is a complete example JSON source for the “Web Search (Serp)” plugin:

```json theme={null}
{
    "id": "f1af15c3-23ba-4548-a123-ea72d9a70dfd",
    "uuid": "f1af15c3-23ba-4548-a123-ea72d9a70dfd",
    "title": "Web Search (Serp)",
    "iconURL": "https://raw.githubusercontent.com/TypingMind/plugin-web-search-serp/refs/heads/main/icon.webp",
    "createdAt": "2025-09-12T05:36:39.890Z",
    "githubURL": "https://github.com/TypingMind/plugin-web-search-serp",
    "sourceUUID": null,
    "oauthConfig": null,
    "userSettings": [
        {
            "name": "serpAPIKey",
            "type": "password",
            "label": "Serp API Key",
            "required": true,
            "description": "Enter your Serp API Key here, if you don't have one, sign up from serpapi.com"
        }
    ],
    "overviewMarkdown": "## Web Search (SerpApi)\n\nThis plugin allows the AI assistant to search for information from the internet in real-time using Google Search.\n\n**🔑 Serp API Key needed**. Click the Settings tab and enter your Serp API Key. To get your API Key, [create a Serp account](https://serpapi.com/)\n\nExample usage:\n\n> What's the gold price today?\n\n> How's the weather in SF at the moment?\n",
    "authenticationType": "AUTH_TYPE_NONE",
    "dynamicContextEndpoints": [],
    "pluginFunctions": [
        {
            "id": "12d8b5b7-9e87-452a-adde-0fb7aa853105",
            "name": "search_web",
            "implementationType": "http",
            "openaiSpec": {
                "name": "search_web",
                "parameters": {
                    "type": "object",
                    "required": [
                        "query"
                    ],
                    "properties": {
                        "query": {
                            "type": "string",
                            "description": "The search term to look up on the web. Be specific and include relevant keywords for better results. For technical queries, include version numbers or dates if relevant."
                        },
                        "explanation": {
                            "type": "string",
                            "description": "One sentence explanation as to why this tool is being used, and how it contributes to the goal."
                        }
                    }
                },
                "description": "Search the web using SERP API (Google search engine) for real-time information about any topic. Use this tool when you need up-to-date information that might not be available in your training data, or when you need to verify current facts. The search results will include relevant snippets and URLs from web pages. This is particularly useful for questions about current events, technology updates, or any topic that requires recent information."
            },
            "code": "",
            "httpAction": {
                "id": "39442ea9-287b-4b06-951d-10291490295a",
                "url": "https://cloud.typingmind.com/api/plugins/serp/search?api_key={serpAPIKey}&engine=google&q={query}&json_restrictor=organic_results[].{title,snippet,source,link}",
                "name": "",
                "method": "GET"
            },
            "outputType": "respond_to_ai"
        }
    ],
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.