@womp/openai-plugin 0.0.0-stage → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -2
- package/dist/index.d.ts +83 -0
- package/dist/index.js +47 -0
- package/package.json +54 -4
package/README.md
CHANGED
|
@@ -1,3 +1,109 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @womp/openai-plugin
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Womp in ChatGPT: the MCP tools, the model's workflow and the cards ChatGPT
|
|
4
|
+
shows. It is a library. swan-backend serves it over HTTP and implements its
|
|
5
|
+
backend; this package has no server, database or credentials of its own.
|
|
6
|
+
|
|
7
|
+
```ts
|
|
8
|
+
import { createServer, BackendRefusal, type WompBackend } from "@womp/openai-plugin"
|
|
9
|
+
|
|
10
|
+
const server = createServer({ backend, subject, onError, instructions }) // one per request
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Architecture
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
ChatGPT ──MCP──► swan-backend ── createServer({ backend, subject }) ──► this package
|
|
17
|
+
▲ │
|
|
18
|
+
└──────────────── WompBackend ◄──────────────────────┘
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
src/
|
|
23
|
+
index.ts public API
|
|
24
|
+
server.ts createServer → registerResources (every card) + registerTools (every tool group)
|
|
25
|
+
backend.ts WompBackend: the contract the host implements
|
|
26
|
+
tools/ one file per tool group (scene.ts); tool.ts: shared helpers
|
|
27
|
+
cards/ one folder per card (design/); bridge.ts: shared host connection
|
|
28
|
+
text.ts what tools and cards say to the model
|
|
29
|
+
prompts/ the workflow the model follows
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Dependency rules
|
|
33
|
+
|
|
34
|
+
- `server` → `tools` → `backend`, `text`, `prompts`, `cards/<card>/data.ts`.
|
|
35
|
+
- `cards/<card>` → its own `data.ts` and `cards/bridge.ts`. A card never imports `tools`, `server` or `backend`.
|
|
36
|
+
- Nothing imports `server` except `index`. Nothing outside this package sees more than the public API.
|
|
37
|
+
|
|
38
|
+
### Public API
|
|
39
|
+
|
|
40
|
+
| Export | Purpose |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `createServer({ backend, subject?, onError?, instructions? })` | the MCP server for one request |
|
|
43
|
+
| `WompBackend` | the contract the host implements |
|
|
44
|
+
| `BackendRefusal` | an error whose message reaches the model as worded |
|
|
45
|
+
|
|
46
|
+
`subject` is the caller as the host established it. `onError` receives every
|
|
47
|
+
error that is not a `BackendRefusal`. `instructions` is appended to the
|
|
48
|
+
server instructions, for tools the host registers itself.
|
|
49
|
+
|
|
50
|
+
## Contract
|
|
51
|
+
|
|
52
|
+
### Host → plugin: `WompBackend`
|
|
53
|
+
|
|
54
|
+
| Method | Does |
|
|
55
|
+
|---|---|
|
|
56
|
+
| `openScene(subject, { designId?, title? })` | finds the caller's design, or makes one, and opens a **build** of it; returns `{ designId, buildId, title }` |
|
|
57
|
+
| `getSceneApi()` | the scene skill, script limits, view names, and `notes` about these designs |
|
|
58
|
+
| `runScript(subject, { designId, code, purpose })` | runs one script on the design; `purpose` becomes the current build's activity, its last screenshot or a fresh render its picture; a failed script returns `ok: false` |
|
|
59
|
+
| `renderScene(subject, { designId, view?, targetId? })` | renders the design; the image also becomes the current build's picture |
|
|
60
|
+
| `finishScene(subject, { designId, title })` | marks the current build done, with this version's title |
|
|
61
|
+
| `getBuild(subject, { designId, buildId })` | a build's status, activity, title and picture; a build that isn't the caller's reads as empty |
|
|
62
|
+
|
|
63
|
+
A build is one round of changes and has one card. Opening a new build never
|
|
64
|
+
changes an earlier one.
|
|
65
|
+
|
|
66
|
+
### Plugin → model and cards
|
|
67
|
+
|
|
68
|
+
- **Identity.** Every tool acts as `subject`. Tool arguments and client `_meta` are never read for identity. Without a subject every tool call fails.
|
|
69
|
+
- **Errors.** A `BackendRefusal` message reaches the model as is. Any other error is one generic failure, reported to `onError`.
|
|
70
|
+
- **Tool metadata states facts.** Descriptions, input schemas and server instructions say what a tool does, never how the model should behave. Behaviour lives in `prompts/` and reaches the model in `load_scene_skill`'s result.
|
|
71
|
+
- **Every tool** declares `ui.visibility`, explicit annotation hints, and `securitySchemes: noauth`. Tools only a card calls are `ui.visibility: ["app"]`.
|
|
72
|
+
- **Card data** is the tool result's `structuredContent`, typed by the card's `data.ts`. Tools map backend types to it; a card never receives backend types.
|
|
73
|
+
- **Cards** are MCP Apps resources (`text/html;profile=mcp-app`): one self-contained HTML file each, loading nothing from outside, with a `ui://` URI that changes with its content.
|
|
74
|
+
|
|
75
|
+
### Tools
|
|
76
|
+
|
|
77
|
+
| Tool | Called by | Card |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| `open_scene` | model | shows `design` |
|
|
80
|
+
| `load_scene_skill` | model | |
|
|
81
|
+
| `run_scene_script` | model | |
|
|
82
|
+
| `render_scene` | model | |
|
|
83
|
+
| `finish_scene` | model | |
|
|
84
|
+
| `get_scene_progress` | `design` card | |
|
|
85
|
+
|
|
86
|
+
## Extending
|
|
87
|
+
|
|
88
|
+
**A card.** A folder in `src/cards/<name>/` with `index.html`, `main.ts` and
|
|
89
|
+
`data.ts`, and a description in `text.ts` (`CARD_DESCRIPTIONS`). The build
|
|
90
|
+
picks it up as `CARDS.<name>`; the tool that shows it sets `ui.resourceUri:
|
|
91
|
+
CARDS.<name>.uri` and returns its `data.ts` shape as `structuredContent`.
|
|
92
|
+
|
|
93
|
+
**A tool group.** `src/tools/<group>.ts` exporting `register<Group>Tools(server,
|
|
94
|
+
backend, run)`, called from `registerTools` in `server.ts`. Its text goes in
|
|
95
|
+
`text.ts`; new backend methods in `backend.ts`.
|
|
96
|
+
|
|
97
|
+
**A contract change** (anything in `backend.ts`) ships with the host's
|
|
98
|
+
implementation in the same release.
|
|
99
|
+
|
|
100
|
+
## Development
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
npm run dev # card preview at http://127.0.0.1:5188/preview/, live from source
|
|
104
|
+
npm test # build the cards, run the tests
|
|
105
|
+
npm run check # format, build, typecheck, tests (CI)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Release: bump the version and tag `vX.Y.Z`; CI publishes to npm. Then bump the
|
|
109
|
+
dependency in swan-backend.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
+
|
|
3
|
+
interface SceneApi {
|
|
4
|
+
skill: {
|
|
5
|
+
name: string;
|
|
6
|
+
version: string;
|
|
7
|
+
instructions: string;
|
|
8
|
+
declarations: string;
|
|
9
|
+
examples: string[];
|
|
10
|
+
};
|
|
11
|
+
limits: {
|
|
12
|
+
timeoutMs: number;
|
|
13
|
+
maxCodeLength: number;
|
|
14
|
+
maxImages: number;
|
|
15
|
+
};
|
|
16
|
+
views: string[];
|
|
17
|
+
notes: string[];
|
|
18
|
+
}
|
|
19
|
+
interface Image {
|
|
20
|
+
data: string;
|
|
21
|
+
mimeType: string;
|
|
22
|
+
}
|
|
23
|
+
interface ScriptResult {
|
|
24
|
+
ok: boolean;
|
|
25
|
+
value?: unknown;
|
|
26
|
+
logs: string[];
|
|
27
|
+
receipts: {
|
|
28
|
+
operation: string;
|
|
29
|
+
status: string;
|
|
30
|
+
}[];
|
|
31
|
+
images: Image[];
|
|
32
|
+
error?: string;
|
|
33
|
+
}
|
|
34
|
+
interface Picture extends Image {
|
|
35
|
+
at: string;
|
|
36
|
+
}
|
|
37
|
+
interface Build {
|
|
38
|
+
status: "building" | "done";
|
|
39
|
+
activity?: string;
|
|
40
|
+
title?: string;
|
|
41
|
+
picture: Picture | null;
|
|
42
|
+
}
|
|
43
|
+
interface WompBackend {
|
|
44
|
+
openScene(subject: string, input: {
|
|
45
|
+
designId?: string;
|
|
46
|
+
title?: string;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
designId: string;
|
|
49
|
+
buildId: string;
|
|
50
|
+
title: string;
|
|
51
|
+
}>;
|
|
52
|
+
getSceneApi(): Promise<SceneApi>;
|
|
53
|
+
runScript(subject: string, input: {
|
|
54
|
+
designId: string;
|
|
55
|
+
code: string;
|
|
56
|
+
purpose: string;
|
|
57
|
+
}): Promise<ScriptResult>;
|
|
58
|
+
renderScene(subject: string, input: {
|
|
59
|
+
designId: string;
|
|
60
|
+
view?: string;
|
|
61
|
+
targetId?: number;
|
|
62
|
+
}): Promise<Image>;
|
|
63
|
+
finishScene(subject: string, input: {
|
|
64
|
+
designId: string;
|
|
65
|
+
title: string;
|
|
66
|
+
}): Promise<void>;
|
|
67
|
+
getBuild(subject: string, input: {
|
|
68
|
+
designId: string;
|
|
69
|
+
buildId: string;
|
|
70
|
+
}): Promise<Build>;
|
|
71
|
+
}
|
|
72
|
+
declare class BackendRefusal extends Error {
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface ServerOptions {
|
|
76
|
+
backend: WompBackend;
|
|
77
|
+
subject?: string;
|
|
78
|
+
onError?: (tool: string, error: unknown) => void;
|
|
79
|
+
instructions?: string;
|
|
80
|
+
}
|
|
81
|
+
declare function createServer({ backend, subject, onError, instructions }: ServerOptions): McpServer;
|
|
82
|
+
|
|
83
|
+
export { BackendRefusal, type WompBackend, createServer };
|