Plugin Manifests
Gestalt plugin packages are described by a manifest file named one of:
plugin.yamlplugin.ymlplugin.json
YAML is the easiest format to author by hand.
Top-Level Shape
A manifest can define exactly one of:
providerwebui
Common Fields
| Field | Purpose |
|---|---|
source | Canonical plugin source identifier. Required. Use github.com/<org>/<repo>/<plugin>. |
version | Plugin version. Required. |
display_name | Human-readable label. |
description | Human-readable description. |
icon_file | Relative path to an SVG icon bundled with the package. |
provider | Provider metadata and optional declarative surfaces. |
webui | UI metadata for UI-only packages. |
artifacts | Packaged executable artifacts keyed by platform. |
Basic YAML Manifest
This example is a declarative-only provider package. It does not need a binary.
source: github.com/acme/plugins/support-api
version: 0.1.0
display_name: Support API
description: Small ticket API
icon_file: assets/icon.svg
provider:
connections:
default:
auth:
type: bearer
credentials:
- name: token
label: API Token
surfaces:
rest:
base_url: https://api.support.example.com
operations:
- name: list_tickets
description: Return open tickets
method: GET
path: /tickets
- name: get_ticket
description: Return one ticket
method: GET
path: /tickets/{ticket_id}Use this style when:
- the provider can be described entirely in YAML
- you do not need custom code
- you want a reusable package that several configs can import
Advanced YAML Manifest
This example shows a provider package with:
- a config schema
- an executable entrypoint
- OpenAPI and upstream MCP surfaces
- managed parameters
- allowed operation aliases
- multiple connections
source: github.com/acme/plugins/support
version: 1.2.3
display_name: Support
description: Tickets, knowledge base, and MCP workspace tools
icon_file: assets/icon.svg
provider:
config_schema_path: schemas/config.schema.yaml
exec:
artifact_path: artifacts/linux/amd64/provider
headers:
X-App-Version: "2026-04-01"
managed_parameters:
- in: path
name: workspace_id
value: primary
connections:
default:
mode: user
auth:
type: oauth2
authorization_url: https://accounts.support.example.com/oauth/authorize
token_url: https://accounts.support.example.com/oauth/token
client_id: ${SUPPORT_CLIENT_ID}
client_secret: ${SUPPORT_CLIENT_SECRET}
scopes:
- tickets.read
- tickets.write
params:
workspace_id:
required: true
from: discovery
discovery:
url: https://api.support.example.com/workspaces
id_path: id
name_path: name
metadata:
workspace_id: id
mcp:
mode: user
auth:
type: mcp_oauth
surfaces:
openapi:
document: openapi.yaml
mcp:
url: https://mcp.support.example.com/mcp
connection: mcp
allowed_operations:
tickets.list:
alias: list_tickets
tickets.get:
alias: get_ticket
artifacts:
- os: linux
arch: amd64
path: artifacts/linux/amd64/provider
sha256: "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"Use this style when:
- the provider includes executable logic
- a reusable package should ship its own connection model
- you want packaged custom code plus spec-backed operations
Post-Connect Discovery
Providers can define provider.connections.default.discovery to perform one
extra authenticated lookup immediately after OAuth or manual connect succeeds.
Gestalt calls the configured URL with the freshly acquired access token, parses
the returned items, and turns them into candidate connections.
Use this when a provider issues user credentials first, but the final stored connection still needs one discovered identifier such as a site, tenant, or workspace.
provider:
connections:
default:
auth:
type: oauth2
authorization_url: https://auth.example.com/authorize
token_url: https://auth.example.com/token
params:
workspace_id:
required: true
description: Workspace identifier discovered after connect
from: discovery
discovery:
url: https://api.example.com/me/workspaces
id_path: id
name_path: display_name
metadata:
workspace_id: idBehavior:
- if discovery returns exactly one item, Gestalt merges its mapped metadata into the stored connection automatically
- if discovery returns multiple items, Gestalt asks the user to choose one
- if discovery returns zero items, connect fails
metadata populates connection metadata, and connection fields marked
with from: discovery are satisfied from that metadata instead of user input.
Web UI Manifest Example
source: github.com/acme/plugins/gestalt-ui
version: 1.0.0
display_name: Custom UI
webui:
asset_root: ui/outAuthoring Notes
- Manifest paths must stay inside the package.
sourceandversionare required.- A manifest defines either
providerorwebui, not both. - Declarative-only provider packages do not require
artifacts. - Executable provider packages do require
artifactsplusprovider.exec.artifact_path. config_schema_pathvalidatesproviders.*.config.- Config schemas may be written in JSON or YAML.
- Only
provider.connections.defaultmay defineparamsanddiscovery. provider.surfaces.rest,provider.surfaces.openapi, andprovider.surfaces.graphqlare mutually exclusive.provider.surfaces.mcpmay be added alongside any of them.
Packaging And Release
Package a local plugin directory:
gestaltd plugin package --input ./my-plugin --output ./dist/my-plugin.tar.gzBuild a release from a plugin source directory:
gestaltd plugin release --version 1.2.3gestaltd plugin release preserves the source manifest format, so
plugin.yaml stays YAML and plugin.json stays JSON in the release package.