Plugins
A plugin is a self-contained web UI, built from HTML, JavaScript, or a framework such as React, that you develop locally and upload to Port. Plugins power custom widgets that render inside dashboards and entity pages using the same catalog data and permissions as the rest of the platform.
You develop and build the plugin in your usual toolchain (for example VS Code, Cursor, or WebStorm), then upload a single compiled HTML file. Port hosts that file for you, there is no separate infrastructure to run. When a custom widget renders, Port serves the plugin, injects authentication, and passes context such as entity data, dashboard filters, page context, and user identity, so your code can call Port APIs safely.
Administrators upload, list, update, and delete plugins using the Port plugins CLI. With the Port MCP server in your IDE, you can also use list_plugins and upsert_plugin for the same tasks (Manage plugins with Port MCP). You can define custom parameters (Params), those fields appear when someone creates or edits a custom widget, which lets a single plugin power different widgets. For example, different blueprints or date properties for a shared calendar-style UI.
Load the plugin skill before you start: it gives your AI agent templates, conventions, and Port-specific patterns built for this task. Call load_skill with identifier create-port-plugin in your MCP client.
Prerequisitesβ
Before you begin, make sure you have the following installed on your machine:
- Node.js (version 18 or higher) - Download from nodejs.org
- npm (comes with Node.js) or yarn
- Git - Download from git-scm.com
- A code editor such as VS Code, Cursor, or WebStorm
You will also need:
- Port admin permissions to upload plugins.
- Your Port client ID and client secret for authentication. See Find your Port credentials.
Getting startedβ
You can get started in two ways:
| Path | Use when you want to⦠|
|---|---|
| Port plugins repository | Build new custom widgets easily with the bundled create-port-plugin Agent Skill and Port MCP in your IDE, browse the marketplace to deploy ready-made widgets, or extend an existing plugin for your catalog. |
| Sample plugin repository | Learn the build-and-upload flow from a minimal blank project, or wire your own UI with React, TypeScript, and the plugins SDK only. |
Both paths produce a single dist/index.html file. After you build, register it in Port with port-plugins upload or with upsert_plugin in MCP (Manage plugins with Port MCP), then add the plugin as a custom widget.
Port plugins repositoryβ
The port-plugins repository on GitHub includes example plugins you can deploy as-is, plus a create-port-plugin Agent Skill for AI-assisted IDEs such as Cursor and Claude Code.
Each plugin folder has its own README with prerequisites, widget parameters, local development steps, and upload commands.
Clone the repository
git clone https://github.com/port-experimental/port-plugins.git
cd port-plugins
Install these tools before you start working with the port-plugins repository. You normally use them together: MCP for catalog context in the IDE, and either the CLI or MCP plugin tools to register the built file.
- Port plugins CLI (
@port-labs/port-plugins-cli) - Register and manage plugins from the terminal or CI. See configure your Port connection before your first upload. - Port MCP server - Use during design to inspect blueprints, relations, properties, and entities. You can also call
list_pluginsandupsert_pluginso uploads stay in the IDE (Manage plugins with Port MCP). Plugin runtime code still uses the Port HTTP API with the host token, not MCP.
Use an existing plugin
Let's deploy an example plugin:
- Open the desired plugin folder (for example
entity-calendarortechdocs). - Follow that folder's README to install dependencies and run
npm run build. - Register the built file in Port using the Port plugins CLI or
upsert_pluginin MCP (Manage plugins with Port MCP).
Create a new plugin
The repository includes a project-scoped Agent Skill at .cursor/skills/create-port-plugin. When you open the cloned repository in Cursor or another IDE that loads skills from .cursor/skills, the skill is available to the agent.
To scaffold or adapt a plugin, ask your IDE agent to build the widget you need (for example, "Create a Port plugin that shows open incidents for the current service"). The skill guides reuse of existing widgets, copying from bundled templates, and compliance with Port constraints (single HTML artifact, CSP, @port-labs/plugins-sdk, and upload-params.json conventions). When the build produces dist/index.html, register it with port-plugins upload from the Port plugins CLI section, or with upsert_plugin in MCP (Manage plugins with Port MCP).
Sample plugin repositoryβ
The port-plugin-sample repository is a minimal React + TypeScript starter wired to the plugins SDK. Use it when you want a blank project without the example widgets or Agent Skill from port-plugins.
1. Clone the sample repository
git clone https://github.com/port-labs/port-plugin-sample.git
cd port-plugin-sample
2. Install dependencies
Inside the project folder, install the required packages:
npm install
3. Run the plugin locally (optional)
To preview your plugin during development, run npm run dev. This starts a local development server (usually at http://localhost:9000).
When running locally, the plugin won't have access to Port's context (user data, entity data, etc.) since it's not embedded in the Port app. Use this mode to verify your UI renders correctly before uploading.
4. Build the plugin
When you're ready to upload, create a production build:
npm run build
This generates dist/index.html, a single self-contained file with all JavaScript and CSS inlined.
Register the plugin in Port using the approach that fits your step (CLI, MCP, or both):
- For terminal or CI, install the CLI and configure your Port connection, then upload a plugin with
port-plugins upload. - From the IDE with MCP connected, you can call
upsert_pluginfor the same registration from the editor (Manage plugins with Port MCP). Uselist_pluginsanytime to list what is already in your organization.
Example plugins in port-plugins document the full upload command (including --params) in each folder's README.
You can confirm the upload in the Plugins Manager. Then add the plugin as a custom widget as instructed below.
Add plugin as a custom widgetβ
After you upload a plugin from either path, add it as a custom widget in Port:
- Go to any dashboard or entity page in Port.
- Click + Widget, select Custom.
- Choose your plugin from the list.
- Configure the parameters and click Create.
For more widget options, see Custom widget.
Plugins SDKβ
@port-labs/plugins-sdk bridges postMessage between your plugin code and the Port web app. When Port serves your plugin, the host passes context such as the user, page, params, entity, optional theme data, and a JWT for Port API calls. On PLUGIN_DATA, the host sends baseUrl, and the React hook exposes it as portApiBaseUrl.
The package includes mergePageFilters for entity search with dashboard page filters, React helpers from @port-labs/plugins-sdk/react, and framework-agnostic patterns. For full API detail, see the plugins SDK package on npm.
Port blocks window.open() for plugins, so you cannot use it to open new windows or tabs from plugin code. If you need links, navigation, or similar behavior, use @port-labs/plugins-sdk 0.1.1 or newer.
Constraints when building pluginsβ
Do not include API keys, passwords, or tokens in widget content or in your uploaded plugin file. They may be exposed to other users or widgets in your organization.
Content security policy (CSP)β
Port serves your plugin inside the browser under a content security policy (CSP) that limits what the page can load and connect to. Design your bundle and network usage to stay within these rules.
-
Scripts and styles - Scripts and styles load only from the plugin origin.
'unsafe-inline'is allowed, so a single HTML file with inlined JavaScript and CSS works as expected. -
Asset loading (
default-src) - Thedefault-srcdirective is set to'self',https://*.getport.io, andhttps://*.port.io. This covers<img>,<video>,<audio>,<source>,@font-face, and similar resource types - asset URLs on those origins load, and every other host is blocked. -
Self-contained assets - To keep your bundle self-contained, you can embed images, fonts, and media directly in the plugin HTML file.
-
Blocked elements - Port blocks common embedding patterns that bypass normal resource loading rules:
object-src 'none'- Blocks<object>and<embed>elements, including common patterns for embedding external players or documents.frame-src 'none'- Blocks<iframe>, so you cannot embed another site's page, player, or document inside the plugin UI.
-
Network requests (
connect-src) -connect-srclimits scripted network APIs (fetch,XMLHttpRequest, WebSockets, and similar) to'self',https://*.getport.io, andhttps://*.port.io. Calls from the plugin to other hosts - for example, third-party analytics or public REST APIs - are blocked. -
Framing (
frame-ancestors) -frame-ancestorsallows the Port web app (on*.getport.ioand*.port.io) to embed your plugin. Arbitrary third-party sites cannot frame it. -
Trusted types -
require-trusted-types-for 'script'enforces trusted types for script-related DOM sinks. If a library assigns raw strings where the browser expects a trusted type, you may need to adjust usage or dependencies.
Technical limitationsβ
- Each plugin artifact is one self-contained HTML file, multi-file bundles or separate asset uploads are not supported.
- The uploaded file must be 10 MB or smaller.
Port plugins CLIβ
The Port plugins CLI (@port-labs/port-plugins-cli) uploads and manages plugins from your terminal or from CI. Install it globally with:
npm install -g @port-labs/port-plugins-cli
For full install steps, commands, authentication, configuration, and plugin metadata limits, see the @port-labs/port-plugins-cli package on npm.
Authenticate the Port plugins CLI with a client ID and client secret, or with an access token. Admin permissions are required to upload and manage plugins. For where to find your credentials, see Find your Port credentials.
Configure your Port connectionβ
Run port-plugins config once to save credentials so you do not pass them on every command. The interactive flow asks for your Port API region (EU or US), then whether to use a client ID + secret or an access token.
port-plugins config
By default, this writes .port/config in your current directory (project scope). For credentials that apply everywhere on your machine:
port-plugins config --global
Non-interactive example (for example in CI):
port-plugins config --client-id "your-client-id" --client-secret "your-client-secret"
You can also authenticate per command with --client-id / --client-secret, --token, or environment variables (PORT_CLIENT_ID, PORT_CLIENT_SECRET, PORT_TOKEN, or PORT_ACCESS_TOKEN). Prefer a config file over putting secrets in shell profile files.
Upload a pluginβ
port-plugins upload \
--file dist/index.html \
--identifier my-plugin \
--title "My Plugin" \
--description "A description of what this plugin does" \
--upsert
Upload with custom parametersβ
If your plugin accepts configuration such as blueprint selection:
port-plugins upload \
--file dist/index.html \
--identifier my-plugin \
--title "My Plugin" \
--params "$(cat params.json)" \
--upsert
List all plugins: port-plugins list
Delete a plugin: port-plugins delete <plugin-identifier>
For the full command reference, see the @port-labs/port-plugins-cli package on npm.
Manage plugins with Port MCPβ
Before you begin (AI-assisted)β
If you're building a new plugin, load the skill first. It contains the build patterns your AI agent needs.
Call load_skill with name: "create-port-plugin" in your MCP client. Port provides the skill for you, with the same intent as the create-port-plugin Agent Skill in the port-plugins repository.
With the Port MCP server in your IDE, list_plugins and upsert_plugin list and register plugins in Port the same way the CLI covers inventory and port-plugins upload. You can mix MCP and the CLI in one project without changing the result in Port.
Using the plugins in Portβ
To add an uploaded plugin to a dashboard or entity page, follow add plugin as a custom widget in the getting started section, or see custom widgets for more widget options.
Plugins managerβ
Admins can open Plugins Manager in Builder to manage plugins for your organization:
- Navigate to the Builder page.
- Click on the Plugins Manager in the left sidebar to manage your uploaded plugins.
The Plugins Manager lists all plugins uploaded to your organization, showing each plugin's identifier, title, description, size, creator, and the custom parameters it exposes (Params). From here, admins can review available plugins before wiring one into a custom widget.
API referenceβ
Use these Port API endpoints to upload, list, update, and delete plugins programmatically: