♻️ Type the MCP plugin with the repo plugin types

Link the MCP plugin to plugins/libs/plugin-types instead of the
published 1.5.0 package, which lacks PenpotMgmt. The repo types
declare the penpotMgmt global, so the inline import in index.d.ts
goes away and the plugin checks against the API it runs with.

Type Context.management as PenpotMgmt without on/off, so new
management methods need no extra listing.

Mark the background plugin mock in load-plugin.spec.ts as
NonNullable: createPlugin can return undefined, and the build
type-check failed on it.
This commit is contained in:
alonso.torres 2026-10-07 15:20:32 +02:00
parent a125977fce
commit 9517f2ac94
7 changed files with 16 additions and 39 deletions

View File

@ -14,7 +14,7 @@
},
"dependencies": {
"@penpot/plugin-styles": "1.5.0",
"@penpot/plugin-types": "1.5.0"
"@penpot/plugin-types": "link:../../../plugins/libs/plugin-types"
},
"devDependencies": {
"cross-env": "^10.1.0",

View File

@ -8,8 +8,6 @@ interface McpOptions {
declare global {
const mcp: undefined | McpOptions;
/** management API; only exposed to plugins running with global scope */
const penpotMgmt: undefined | null | import("../../../../plugins/libs/plugin-types").PenpotMgmt;
}
export {};

View File

@ -2,6 +2,7 @@ import { ExecuteCodeTaskHandler } from "./task-handlers/ExecuteCodeTaskHandler";
import { Task, TaskHandler } from "./TaskHandler";
import { formatTaskError } from "./ErrorUtils";
import type { PluginConnectionInit } from "../../common/src";
import type { WorkspaceContext } from "@penpot/plugin-types";
/**
* indicates whether the plugin is running in an environment with the Penpot-integrated remote MCP server
@ -102,7 +103,7 @@ penpot.ui.onMessage<
* Provides the workspace metadata of this tab.
* Without the management API, the metadata is derived from the open file.
*/
function currentWorkspace(): NonNullable<typeof penpotMgmt>["workspace"] {
function currentWorkspace(): WorkspaceContext {
if (management) {
return management.workspace;
}

View File

@ -5302,15 +5302,7 @@ Context:
```
interface Context {
management?: Pick<
PenpotMgmt,
"workspace"
| "openFile"
| "listProjects"
| "listFiles"
| "createProject"
| "createFile",
>;
management?: Omit<PenpotMgmt, "on" | "off">;
version: string;
root: Shape | null;
currentFile: File | null;
@ -5384,16 +5376,11 @@ Context:
Properties:
management: |-
```
readonly management?: Pick<
PenpotMgmt,
"workspace"
| "openFile"
| "listProjects"
| "listFiles"
| "createProject"
| "createFile",
>
readonly management?: Omit<PenpotMgmt, "on" | "off">
```
Backs `penpotMgmt`. Its events go through the plugin listener registry,
so `on` and `off` are not part of it.
version: |-
```
readonly version: string

9
mcp/pnpm-lock.yaml generated
View File

@ -188,8 +188,8 @@ importers:
specifier: 1.5.0
version: 1.5.0
'@penpot/plugin-types':
specifier: 1.5.0
version: 1.5.0
specifier: link:../../../plugins/libs/plugin-types
version: link:../../../plugins/libs/plugin-types
devDependencies:
cross-env:
specifier: ^10.1.0
@ -663,9 +663,6 @@ packages:
'@penpot/plugin-styles@1.5.0':
resolution: {integrity: sha512-rwXFBRPd0IZs3ens+eRT8oA5WqkQgF6xlW6fCfH7U1NHRjej9HH7vTGXmfjoIVml6Xx1sbyYHZVxkQC8Ub8+zA==}
'@penpot/plugin-types@1.5.0':
resolution: {integrity: sha512-hFk4Rx66rLaSUWoN6bhxXkDI2ymwKg9xokdslvZvXM5MSmEmfhsJKUMwtuzgYWljbbfaQhK+DjK8g8yVbbavtA==}
'@pinojs/redact@0.4.0':
resolution: {integrity: sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==}
@ -1880,8 +1877,6 @@ snapshots:
'@penpot/plugin-styles@1.5.0': {}
'@penpot/plugin-types@1.5.0': {}
'@pinojs/redact@0.4.0': {}
'@rolldown/binding-android-arm-eabi@1.2.11':

View File

@ -902,15 +902,11 @@ export interface PenpotMgmt {
* Represents the context of Penpot, providing access to various Penpot functionalities and data.
*/
export interface Context {
readonly management?: Pick<
PenpotMgmt,
| 'workspace'
| 'openFile'
| 'listProjects'
| 'listFiles'
| 'createProject'
| 'createFile'
>;
/**
* Backs `penpotMgmt`. Its events go through the plugin listener registry,
* so `on` and `off` are not part of it.
*/
readonly management?: Omit<PenpotMgmt, 'on' | 'off'>;
/**
* Returns the current penpot version.
*/

View File

@ -216,7 +216,7 @@ describe('plugin-loader', () => {
pluginId: 'background-plugin',
allowBackground: true,
},
} as unknown as Awaited<ReturnType<typeof createPlugin>>;
} as unknown as NonNullable<Awaited<ReturnType<typeof createPlugin>>>;
vi.mocked(createPlugin).mockResolvedValue(backgroundPluginApi);
await loadPlugin(manifest);