@codemation/agent-skills 0.2.0 → 0.4.0

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.
@@ -2,10 +2,16 @@
2
2
  name: codemation-custom-node-development
3
3
  description: Guides Codemation custom node development with `defineNode(...)` (`execute` per item), `defineBatchNode(...)` (batch `run`), reusable node modules, credential-aware nodes, and the class-based node fallback for advanced cases. Use when creating or updating custom nodes for apps or plugin packages.
4
4
  compatibility: Designed for Codemation apps and plugin packages that define reusable nodes.
5
+ tags: node, custom, plugin
6
+ uses: "@codemation/core"
5
7
  ---
6
8
 
7
9
  # Codemation Custom Node Development
8
10
 
11
+ ## Mental model
12
+
13
+ Custom nodes are the extension point for reusable business logic that doesn't belong inline in a workflow callback. `defineNode(...)` wraps a per-item `execute` function with a typed contract (input schema, credential slots, output shape); the engine calls it once per item. `defineBatchNode(...)` is the batch variant for logic that must see all items at once. Nodes compose into workflows via config class instances — the node definition is separate from the config class used to wire it into a workflow.
14
+
9
15
  ## Use this skill when
10
16
 
11
17
  Use this skill for reusable custom node work, whether the node lives inside an app or a published plugin package.
@@ -45,6 +51,8 @@ export const uppercaseNode = defineNode({
45
51
  });
46
52
  ```
47
53
 
54
+ For full patterns — credential-slotted nodes, batch nodes, fan-out, binary payloads, and test kit usage — use your harness's example-discovery tool: `find_examples({ query: "defineNode" })` or `find_examples({ query: "defineBatchNode" })`.
55
+
48
56
  ## Read next
49
57
 
50
58
  - `references/define-node-per-item.md` — full `defineNode(...)` contract, `inputSchema`, `itemExpr`, fan-out, assertion nodes, and `WorkflowTestKit` usage. Load this when writing or debugging a per-item node.
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: codemation-document-scanner
3
+ description: CodemationDocumentScanner node — managed document/invoice/image extraction via the Codemation doc-scanner service. No Azure credentials required. Read before writing any workflow that scans documents, invoices, or images.
4
+ compatibility: Codemation core-nodes. Requires @codemation/core-nodes import.
5
+ tags: ocr, document, invoice, image, scan, extract, managed, confidence
6
+ uses: "@codemation/core-nodes"
7
+ ---
8
+
9
+ # Codemation Document Scanner Node
10
+
11
+ > **Start here: call `find_examples` before reading further.**
12
+ >
13
+ > - `find_examples({ query: "CodemationDocumentScanner" })` — node-level usage and all analyzerType variants
14
+ > - `find_examples({ query: "invoice scan post accounting" })` — end-to-end invoice extraction scenario
15
+ > - `find_examples({ query: "document scanner confidence fields" })` — how to enable per-field confidence scores
16
+
17
+ ## Use this skill when
18
+
19
+ Writing a workflow that extracts text and/or structured fields from documents, invoices, or images
20
+ using the Codemation managed scanning service. No Azure credentials are required — the service is
21
+ pre-wired to the platform.
22
+
23
+ Use `codemation-workflow-dsl` for surrounding workflow structure.
24
+ Use `codemation-ai-agent-node` if you need to pass the extracted markdown to an LLM for further processing.
25
+
26
+ ## When to use CodemationDocumentScanner vs the standalone OCR nodes
27
+
28
+ | Situation | Use |
29
+ | ------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
30
+ | Managed platform deployment, no Azure credential | `codemationDocumentScannerNode` (this skill) |
31
+ | Self-hosted / BYOK Azure Content Understanding | `analyzeDocumentNode` / `analyzeInvoiceNode` / `analyzeImageNode` from `@codemation/core-nodes-ocr` |
32
+
33
+ `codemationDocumentScannerNode` calls the internal `doc-scanner` service via HMAC — the workspace holds
34
+ no Azure key. The standalone OCR nodes call Azure directly using a per-workspace credential.
35
+
36
+ ## Choosing `analyzerType`
37
+
38
+ | `analyzerType` | When to use | Azure analyzer | Field extraction | Confidence opt-in supported |
39
+ | -------------- | ----------------------------------------------- | ----------------------------------------------------------------------- | ---------------------- | --------------------------------------- |
40
+ | `"document"` | General PDFs, Word docs, HTML, text-heavy files | `prebuilt-document` | Yes | Yes |
41
+ | `"invoice"` | Invoices, receipts — always prebuilt-invoice | `prebuilt-invoice` | Yes | Yes |
42
+ | `"image"` | Photos, screenshots, diagrams | `prebuilt-imageAnalyzer` | No (markdown only) | No — image carries no extraction charge |
43
+ | `"auto"` | Unknown mime type at author time | Routes on `Content-Type`: `image/*` → image, everything else → document | Depends on routed type | Depends on routed type |
44
+
45
+ **Default is `"auto"`.** Set an explicit type whenever you know the content class — it avoids
46
+ unnecessary re-routing and makes the workflow self-documenting.
47
+
48
+ ## Output shape
49
+
50
+ ```ts
51
+ {
52
+ markdown: string; // full text content
53
+ fields: Record<
54
+ string,
55
+ {
56
+ value: unknown; // extracted scalar, date ISO string, nested object, or array
57
+ confidence: number | null; // 0–1 when includeConfidence:true; null otherwise
58
+ }
59
+ >;
60
+ }
61
+ ```
62
+
63
+ `item.json.markdown` is the Markdown rendering of the document.
64
+ `item.json.fields` is a flat-or-nested map of structured fields found by the analyzer.
65
+ For `analyzerType: "image"`, `fields` is always `{}`.
66
+ Fields may be sparse or absent for generic documents — extraction is best-effort.
67
+
68
+ ## WARNING: How to enable per-field confidence scores (LD6)
69
+
70
+ **By default, `confidence` is `null` on every field.** This keeps token cost low for the majority
71
+ of workflows that only need `value`.
72
+
73
+ To get a populated `confidence` (0–1 float) on each field, set `includeConfidence: true`:
74
+
75
+ ```ts
76
+ codemationDocumentScannerNode.create(
77
+ {
78
+ binaryField: "data",
79
+ analyzerType: "invoice",
80
+ includeConfidence: true, // ← opt-in: fields carry confidence 0–1
81
+ },
82
+ "Scan invoice",
83
+ "scan-invoice",
84
+ );
85
+ ```
86
+
87
+ **Cost implication:** enabling confidence routes the request to a confidence-enabled analyzer variant,
88
+ which roughly doubles the contextualization token count for document/invoice analyzers.
89
+ Only enable it when your downstream logic actually reads `field.confidence`.
90
+
91
+ Images (`analyzerType: "image"`) and auto-routed-to-image requests carry no field-extraction charge
92
+ regardless of this flag — they silently ignore `includeConfidence` (confidence stays `null`, never a 400).
93
+
94
+ ## API usage
95
+
96
+ ```ts
97
+ import { codemationDocumentScannerNode } from "@codemation/core-nodes";
98
+
99
+ codemationDocumentScannerNode.create(
100
+ {
101
+ binaryField?: string; // key on item.binary — default "data"
102
+ analyzerType?: "document" | "invoice" | "image" | "auto"; // default "auto"
103
+ contentType?: string; // MIME type override — falls back to attachment.mimeType
104
+ includeConfidence?: boolean; // default false — see cost note above
105
+ maxBytes?: number; // size cap before reading; default 50 MiB (LD10)
106
+ },
107
+ label?: string, // node label on the canvas
108
+ nodeId?: string, // explicit stable id — set when output is used downstream
109
+ )
110
+ ```
111
+
112
+ Set an explicit `nodeId` whenever downstream nodes reference this node's output by id, or when
113
+ the node may be renamed later (avoids credential-binding orphaning).
114
+
115
+ ## Consuming fields downstream
116
+
117
+ ```ts
118
+ import type { DocScannerOutput, DocScannerField } from "@codemation/core-nodes";
119
+
120
+ // item.json after codemationDocumentScannerNode:
121
+ // DocScannerOutput = { markdown: string; fields: Record<string, DocScannerField> }
122
+ // DocScannerField = { value: unknown; confidence: number | null }
123
+
124
+ new Callback<DocScannerOutput>("Use fields", (items, _ctx) =>
125
+ items.map((item) => {
126
+ const vendorName = item.json.fields["VendorName"]?.value as string | undefined;
127
+ const vendorConf = item.json.fields["VendorName"]?.confidence; // null unless includeConfidence:true
128
+ return { ...item, json: { ...item.json, vendorName, vendorConf } };
129
+ }),
130
+ );
131
+ ```
132
+
133
+ ## Read next when needed
134
+
135
+ - `codemation-workflow-dsl` — workflow builder, trigger types, fluent vs low-level API.
136
+ - `codemation-ai-agent-node` — pass `item.json.markdown` to an LLM for summarisation or extraction.
@@ -2,53 +2,40 @@
2
2
  name: codemation-framework-concepts
3
3
  description: Explains Codemation package boundaries, runtime concepts, observability shape, and the normal consumer mental model. Use when the user asks where code belongs across `@codemation/core`, `@codemation/host`, `@codemation/next-host`, `@codemation/cli`, workflows, plugins, credentials, activation, telemetry, or runtime modes. Read this first when starting any Codemation task — it points at the right skill for the work.
4
4
  compatibility: Designed for Codemation apps, plugins, and framework contributors.
5
+ tags: concepts, architecture
5
6
  ---
6
7
 
7
8
  # Codemation Framework Concepts
8
9
 
9
- ## Use this skill when
10
+ ## Mental model
10
11
 
11
- Use this skill to explain package ownership, runtime shape, observability boundaries, and the boundary between consumer code and framework code.
12
+ Codemation is a workflow engine with a layered package structure. `@codemation/core` owns the engine and runtime contracts (must stay pure — no HTTP, UI, or vendor SDKs). `@codemation/host` adds persistence, credentials, APIs, and scheduler wiring. `@codemation/next-host` is the framework UI shell. `@codemation/cli` runs local development, build, and serve. Consumer apps define behavior in `codemation.config.ts` and `src/workflows/` — they never touch core internals.
12
13
 
13
- Do not use this skill as a substitute for detailed CLI, workflow DSL, or plugin implementation guidance when the user already knows the concept they need.
14
+ ## When to use / when NOT
14
15
 
15
- ## Core map
16
+ Use this skill to orient on package ownership, runtime shape, observability boundaries, and the consumer/framework divide.
17
+ Do not use as a substitute for detailed CLI, workflow DSL, or plugin implementation guidance when you already know which skill you need.
16
18
 
17
- 1. `@codemation/core` owns the engine, runtime contracts, and workflow DSL foundations.
18
- 2. `@codemation/host` adds config loading, persistence, credentials, APIs, and scheduler wiring.
19
- 3. `@codemation/next-host` owns the framework UI.
20
- 4. `@codemation/cli` runs local development, build, serve, and user commands.
21
- 5. Consumer apps define `codemation.config.ts` and workflow files.
19
+ ## Core concepts
22
20
 
23
- ## Important concepts
24
-
25
- - workflows define behavior
26
- - triggers start runs
27
- - nodes process items
28
- - items carry workflow data
29
- - credentials provide typed runtime resources
30
- - activation is framework-managed and happens in the UI
31
- - telemetry is observability-first: traces, spans, artifacts, and metric points are framework-owned runtime data
32
- - run retention and telemetry retention can differ, so trend data can outlive raw run state
33
- - **workflow testing** is a first-class primitive: a `TestTrigger` node yields one item per test case, the orchestrator dispatches a workflow run per case with `executionOptions.testContext` set, and `Assertion` nodes (`emitsAssertions: true`) record per-run results into `TestAssertion` rows; the canvas exposes a Tests tab parallel to Live and Executions
34
-
35
- ## Runtime rule of thumb
36
-
37
- 1. Start with the minimum setup.
38
- 2. Move to shared PostgreSQL and Redis when execution needs separate worker infrastructure.
39
- 3. Keep workflow code stable while the runtime shape grows around it.
40
- 4. Treat telemetry as part of the runtime contract, not as ad-hoc node-local logging.
21
+ - **workflows** define behavior; **triggers** start runs; **nodes** process items; **items** carry `item.json` data.
22
+ - **credentials** provide typed runtime resources (bound per operator instance, not per workflow code).
23
+ - **activation** is framework-managed and happens in the UI — consumer code does not call it directly.
24
+ - **telemetry** is observability-first: traces, spans, artifacts, and metric points are framework-owned runtime data.
25
+ - **workflow testing** is a first-class primitive: `TestTrigger` yields one item per test case; `Assertion` nodes record per-run results into `TestAssertion` rows; the canvas exposes a Tests tab.
26
+ - **run retention** and **telemetry retention** can differ — trend data can outlive raw run state.
41
27
 
42
28
  ## Where to go next
43
29
 
44
- - Authoring workflows → `codemation-workflow-dsl`
45
- - Building a reusable node → `codemation-custom-node-development`
46
- - Building a credential type → `codemation-credential-development`
47
- - Packaging as a plugin `codemation-plugin-development`
48
- - Calling an MCP server from a workflow `codemation-mcp-capabilities`
49
- - CLI commands / dev loop → `codemation-cli`
30
+ | Task | Skill |
31
+ | ------------------------------------- | ------------------------------------ |
32
+ | Authoring workflows | `codemation-workflow-dsl` |
33
+ | Building a reusable node | `codemation-custom-node-development` |
34
+ | Building a credential type | `codemation-credential-development` |
35
+ | Packaging as a plugin | `codemation-plugin-development` |
36
+ | Calling an MCP server from a workflow | `codemation-mcp-capabilities` |
37
+ | CLI commands / dev loop | `codemation-cli` |
50
38
 
51
39
  ## Read next when needed
52
40
 
53
41
  - Read `references/architecture-map.md` for package ownership and runtime-mode guidance.
54
- - Use the `codemation-workflow-dsl` skill (and its `references/workflow-testing.md`) for hands-on test authoring with TestTrigger / IsTestRun / Assertion.
@@ -2,84 +2,52 @@
2
2
  name: codemation-mcp-capabilities
3
3
  description: Discover MCP servers registered on the Codemation control plane. Use before authoring agent workflows that reference mcpServers to find available server ids and their credential requirements.
4
4
  compatibility: Requires an installation paired with a connected control plane (Sprint 2+).
5
+ tags: mcp, agent, tool
5
6
  ---
6
7
 
7
8
  # Codemation MCP Capabilities
8
9
 
9
- ## Use this skill when
10
+ ## Mental model
10
11
 
11
- Use this skill before writing `agent({ mcpServers: ["..."] })` to discover what server ids are
12
- available and what credential types they require. Without it, you'd have to guess server ids or
13
- ask the user.
12
+ MCP servers extend `AIAgent` with tool access to external services (Gmail, Sheets, etc.). Server ids and credential requirements come from the control-plane registry — they are not hard-coded in framework code. The agent's `mcpServers` array contains stable server id slugs; each declared server surfaces a credential slot the operator must bind in the canvas before activation.
14
13
 
15
- ## How to search
14
+ ## When to use / when NOT
16
15
 
17
- Call `GET /api/registry/capabilities?query=<search term>` on the control-plane API.
18
- The endpoint is session-authenticated (the control-plane session cookie is forwarded automatically
19
- when called from within the workspace's paired context).
16
+ Use this skill before writing `agent({ mcpServers: ["..."] })` to discover available server ids and their credential types.
17
+ Do not use for general AIAgent authoring read `codemation-ai-agent-node` for that.
18
+
19
+ ## Managed mode: CP-loaded MCP servers (default path)
20
+
21
+ In **managed mode**, MCP servers are loaded from the **control plane (CP)** — not declared in plugin code. Discover available servers by querying the CP registry:
20
22
 
21
23
  ```
22
24
  GET /api/registry/capabilities?query=gmail
23
25
  ```
24
26
 
25
- Response shape (array of capability objects):
26
-
27
- ```json
28
- [
29
- {
30
- "kind": "mcp-server",
31
- "id": "gmail",
32
- "displayName": "Gmail",
33
- "description": "Read, send, and manage Gmail messages and labels.",
34
- "acceptedCredentialTypes": ["oauth.google.gmail"]
35
- }
36
- ]
37
- ```
27
+ Response contains objects with `{ kind, id, displayName, description, acceptedCredentialTypes }`. Use `id` in the workflow's `mcpServers` array. An empty `query` string returns all registered servers.
38
28
 
39
- An empty query string returns all registered servers.
40
-
41
- ## Response fields
42
-
43
- | Field | Type | Notes |
44
- | ------------------------ | -------- | --------------------------------------------------------------------- |
45
- | `kind` | string | Always `"mcp-server"` for now. Future: `"node"`, `"credential-type"` |
46
- | `id` | string | Stable slug — add this string to the agent's mcpServers array |
47
- | `displayName` | string | Human-readable name for UI or explanations |
48
- | `description` | string | What the server does |
49
- | `acceptedCredentialTypes`| string[] | Credential type ids accepted by this server (empty = no credential) |
50
-
51
- ## Credential types
52
-
53
- - **`"oauth.google.gmail"`** — user must connect a Google account credential instance via the
54
- credential dialog before the workflow runs. The same credential instance can be shared between
55
- a `GmailTrigger` node and the Gmail MCP server.
56
- - **`"bearer_token"`** etc. — user configures a static credential via the credential dialog.
57
- - **empty array** — no credential required. The server is usable immediately.
58
-
59
- ## Using results in workflow config
60
-
61
- The `id` field from the response is added to the agent's `mcpServers` array. Each entry
62
- surfaces a credential slot on the materialized MCP connection node (same shape as
63
- ChatModel and Tool connection nodes); the user picks a specific credential instance via
64
- the canvas credential dropdown — same flow as a trigger credential. A user may have
65
- multiple instances of the same type (personal vs work Gmail); the dropdown surfaces all
66
- matching instances.
67
-
68
- ```ts
69
- new AIAgent({
70
- name: "Gmail reader",
71
- mcpServers: ["gmail"],
72
- // ...
73
- });
74
- ```
29
+ For a full wired example — cron workflow + AIAgent + mcpServers — use your harness's example-discovery tool: `find_examples({ query: "AIAgent gmail mcpServers" })` or `find_examples({ query: "mcp server" })`.
30
+
31
+ ## Non-managed: plugin-declared MCP servers
32
+
33
+ In self-hosted / non-managed deployments, MCP servers can also be declared via `mcpServers: [...]` in a `definePlugin(...)` call. This is a framework-author pattern — do not use it in managed-mode workflows. See `references/plugin-anatomy.md` in the `codemation-plugin-development` skill for the plugin declaration syntax.
34
+
35
+ ## Decision branches & gotchas
36
+
37
+ **Credential types:** `"oauth.google.gmail"` requires the user to connect a Google account via the credential dialog before the workflow runs. The same instance can be shared between a `GmailTrigger` and the Gmail MCP server. An empty `acceptedCredentialTypes` array means no credential is needed.
38
+
39
+ **Multiple instances:** a user may have multiple instances of the same credential type (personal vs work Gmail). The canvas credential dropdown surfaces all matching instances — the operator picks the one to bind.
40
+
41
+ **Bind via UI only:** there is no inline credential field on the workflow definition. The operator binds the credential instance via the canvas credential dropdown before activation.
42
+
43
+ **Typical flow (managed):**
75
44
 
76
- Bind the credential instance via the UI before activation; there is no inline credential
77
- field on the workflow definition.
45
+ 1. `GET /api/registry/capabilities?query=<term>` find `id` and `acceptedCredentialTypes`.
46
+ 2. Add `id` to `mcpServers` in the `AIAgent` config.
47
+ 3. Report: "The user will need to bind a `<type>` credential instance via the canvas before activating."
78
48
 
79
- ## Example flow
49
+ ## Anti-patterns
80
50
 
81
- 1. User asks: "Build a workflow that reads Gmail and summarises unread messages."
82
- 2. Call `GET /api/registry/capabilities?query=gmail` find `id: "gmail"`, `acceptedCredentialTypes: ["oauth.google.gmail"]`.
83
- 3. Report back: "Gmail MCP is available. The user will need to bind a `oauth.google.gmail` credential instance."
84
- 4. In the workflow, use `mcpServers: ["gmail"]`.
85
- 5. The user binds their credential instance via the canvas credential dropdown before activating.
51
+ - Do not guess server ids always query the registry first.
52
+ - Do not add `acceptedCredentialTypes` to the workflow definition credential binding is UI-driven, not code-driven.
53
+ - Do not declare MCP servers inside plugin code for managed-mode workflows use the CP registry instead.
@@ -2,92 +2,28 @@
2
2
  name: codemation-plugin-development
3
3
  description: Guides Codemation plugin package development, including `definePlugin(...)`, plugin sandboxes, custom nodes, custom credentials, and publishable plugin package structure. Use when building or updating a Codemation plugin package or the plugin starter template.
4
4
  compatibility: Designed for Codemation plugin packages and the Codemation plugin starter template.
5
+ tags: plugin, node, package
5
6
  ---
6
7
 
7
8
  # Codemation Plugin Development
8
9
 
9
- ## Use this skill when
10
+ ## Mental model
10
11
 
11
- Use this skill for published plugin packages, plugin starter work, and sandbox-driven plugin development.
12
+ A Codemation plugin is an npm package with a `codemation.plugin.ts` composition root that calls `definePlugin(...)`. It registers custom nodes and credential types, optionally declares MCP servers, and ships a sandbox app so the plugin is immediately testable. Consumers load the built JavaScript entry (`package.json#codemation.plugin`) — not TypeScript source. Plugin code follows the same `defineNode` / `defineCredential` patterns as app-level code; the plugin boundary is purely about packaging and distribution.
12
13
 
13
- Do not use this skill for ordinary consumer workflow-only changes unless the work needs plugin packaging or reusable extension boundaries.
14
+ ## When to use / when NOT
14
15
 
15
- ## Default approach
16
+ **Plugin authoring is a framework-author / non-managed task.** Managed-mode agents work with credential slots and workflow DSL — they do not author or modify plugin packages.
16
17
 
17
- 1. Treat `codemation.plugin.ts` as the plugin composition root.
18
- 2. Register custom credentials and custom nodes from explicit modules.
19
- 3. Keep the sandbox app small and useful so plugin behavior is testable immediately.
20
- 4. Prefer helper-based node and credential definitions first, then drop to class-based APIs only when needed.
18
+ Use this skill for published plugin packages, plugin starter work, and sandbox-driven plugin development. Do not use for ordinary consumer workflow-only changes.
21
19
 
22
- ## Plugin rules
20
+ ## Decision branches & gotchas
23
21
 
24
- 1. Export a plugin with `definePlugin(...)`.
25
- 2. Keep plugin registration separate from node and credential implementation modules.
26
- 3. Use the sandbox app to exercise the plugin right away.
27
- 4. Keep the package publishable like a normal npm package.
28
- 5. Treat `codemation.plugin.ts` as the plugin repo's source composition root; consumer projects should load the built JavaScript entry declared in `package.json#codemation.plugin`.
22
+ **MCP servers in plugins:** Plugin-declared `mcpServers` is a non-managed pattern for self-hosted / framework-author scenarios. In managed mode, MCP servers are loaded from the control plane — see `codemation-mcp-capabilities` for the managed path.
29
23
 
30
- ## Common plugin pieces
31
-
32
- - `codemation.plugin.ts`: plugin registration and sandbox app source, compiled to the published plugin entry in `dist/`
33
- - `src/nodes/*`: custom node definitions (`defineNode` → **`execute`**; `defineBatchNode` → batch **`run`**)
34
- - `src/credentialTypes/*`: custom credential definitions
35
- - `src/index.ts`: package exports
36
- - `test/*.test.ts` (optional): Vitest + `WorkflowTestKit` from `@codemation/core/testing` for engine-backed unit tests without starting the full host (`pnpm test`)
37
-
38
- ## Packaging guardrail
39
-
40
- - `package.json#codemation.plugin` should point at runnable JavaScript such as `./dist/codemation.plugin.js`.
41
- - Do not rely on consumers TypeScript-loading plugin files from `node_modules`.
42
- - Prefer publishing `dist/**` plus package metadata/docs rather than shipping source-only plugin entry files as runtime dependencies.
43
-
44
- ## Unit tests (`WorkflowTestKit`)
45
-
46
- Import **`WorkflowTestKit`** from **`@codemation/core/testing`**. Use **`registerDefinedNodes([...])`** for `defineNode` packages, then **`runNode({ node: yourNode.create(...), items })`** or **`run({ workflow, items })`** for fuller graphs. Prefer this for fast node tests; use **`codemation dev:plugin`** when you need the UI and persistence.
47
-
48
- ## Declaring MCP servers from a plugin (`mcpServers?`)
49
-
50
- A plugin can declare MCP servers that the framework merges into its in-memory catalog at startup. Use this for providers that need non-standard auth, custom adapter logic, or are shipping alongside custom nodes. For standard SaaS providers (OAuth via broker, plain bearer/API key), prefer the control-plane registry instead — no plugin code required.
51
-
52
- ### When to use plugin-declared MCP servers
53
-
54
- - The provider's MCP server has non-standard auth the generic credential types cannot express.
55
- - The plugin already ships custom nodes for the same provider and wants to co-locate the MCP declaration.
56
- - Self-hosted deployments where no control-plane registry is available.
57
-
58
- ### Required fields
59
-
60
- ```ts
61
- import { definePlugin } from "@codemation/host/authoring";
62
- import type { McpServerDeclaration } from "@codemation/core";
63
-
64
- const myServer: McpServerDeclaration = {
65
- id: "my-service", // globally unique slug: /^[a-z0-9-]+$/
66
- displayName: "My Service",
67
- description: "Provides MCP tools for My Service.",
68
- transport: "http",
69
- url: "https://mcp.my-service.com",
70
- // Credential types this server accepts. Users bind a credential instance
71
- // per slot via the UI. Omit (or set to []) for servers requiring no auth.
72
- acceptedCredentialTypes: ["my-service.bearer-token"],
73
- };
74
-
75
- export default definePlugin({
76
- mcpServers: [myServer],
77
- // credentials, nodes, register, etc.
78
- });
79
- ```
80
-
81
- ### Merge precedence
82
-
83
- The framework merges from three sources in this order (last-write-wins on `id` collisions):
84
-
85
- 1. **Plugin** (lowest) — code in `codemation.plugin.ts`
86
- 2. **`codemation.config.ts`** — dev/self-host declarations
87
- 3. **Control-plane registry** (highest) — managed-mode fast lane; shadows plugin declarations to fix descriptions without a plugin release
88
-
89
- A warning is logged when a higher-priority source shadows a plugin declaration. This is intentional.
24
+ **Publishing guardrail:** `package.json#codemation.plugin` must point at runnable JavaScript (`./dist/codemation.plugin.js`). Do not rely on consumers TypeScript-loading plugin files from `node_modules`.
90
25
 
91
26
  ## Read next when needed
92
27
 
93
- - Read `references/plugin-structure.md` for package layout and node-versus-credential guidance.
28
+ - Read `references/plugin-anatomy.md` for the full `definePlugin(...)` code, package layout, sandbox setup, MCP server declaration, binary payload rules, and publishing guidance.
29
+ - Read `references/plugin-structure.md` for a concise package layout reference.
@@ -0,0 +1,115 @@
1
+ # Plugin Anatomy
2
+
3
+ Plugin authoring is a **framework-author / non-managed task**. Managed-mode agents almost never need to create or modify plugin packages — they work with credential slots and workflow DSL. This reference is for developers building and publishing reusable Codemation plugin packages.
4
+
5
+ ## Quickstart
6
+
7
+ ```ts
8
+ import { definePlugin } from "@codemation/host/authoring";
9
+
10
+ export default definePlugin({
11
+ nodes: [myNode],
12
+ credentials: [myCredentialType],
13
+ // mcpServers: [...], // optional — see MCP section below
14
+ });
15
+ ```
16
+
17
+ ## Plugin package layout
18
+
19
+ ```text
20
+ codemation.plugin.ts ← composition root; calls definePlugin(...)
21
+ src/
22
+ nodes/ ← defineNode / defineBatchNode / defineRestNode files
23
+ credentialTypes/ ← defineCredential files
24
+ index.ts ← public package exports (types, session shapes)
25
+ test/
26
+ *.test.ts ← Vitest + WorkflowTestKit tests
27
+ ```
28
+
29
+ ## Composition root (`codemation.plugin.ts`)
30
+
31
+ The single file that:
32
+
33
+ - calls `definePlugin(...)` and registers nodes + credentials
34
+ - optionally defines a sandbox app via `defineCodemationApp(...)`
35
+
36
+ Consumers discover the plugin through `package.json#codemation.plugin`, which must point at built JavaScript in `dist/` — NOT TypeScript source.
37
+
38
+ ## Node guidance
39
+
40
+ - Start with `defineNode(...)` and `execute(...)` for per-item nodes (most common).
41
+ - Use `defineBatchNode(...)` only when the node must process the whole activation batch in one `run(items, ...)`.
42
+ - Keep runtime logic close to the node definition; use class-based APIs only when you need constructor-injected collaborators.
43
+
44
+ ## Credential guidance
45
+
46
+ - Start with `defineCredential(...)`.
47
+ - Build typed sessions in `createSession(...)`.
48
+ - Implement `test(...)` so operators can validate configuration before activation.
49
+ - For OAuth2 redirect flows, use the URL-template variant (`auth: { kind: "oauth2", authorizeUrl, tokenUrl, scopes }`).
50
+ - See the `codemation-credential-development` skill for detailed credential patterns.
51
+
52
+ ## Declaring MCP servers in a plugin
53
+
54
+ > **Non-managed pattern.** In managed mode, MCP servers are loaded from the control plane — see `codemation-mcp-capabilities`. Plugin-declared MCP servers are for self-hosted / framework-author scenarios.
55
+
56
+ ```ts
57
+ import { definePlugin } from "@codemation/host/authoring";
58
+ import type { McpServerDeclaration } from "@codemation/host/authoring";
59
+
60
+ const myMcpServer: McpServerDeclaration = {
61
+ id: "my-provider-mcp", // globally unique slug /^[a-z0-9-]+$/
62
+ displayName: "My Provider",
63
+ description: "Exposes My Provider tools to AIAgent.",
64
+ transport: "streamable-http",
65
+ url: "https://my-provider.example.com/mcp",
66
+ acceptedCredentialTypes: ["my-provider.api-key"],
67
+ };
68
+
69
+ export default definePlugin({
70
+ nodes: [myNode],
71
+ credentials: [myCredentialType],
72
+ mcpServers: [myMcpServer],
73
+ });
74
+ ```
75
+
76
+ **Merge precedence:** plugin declarations < `codemation.config.ts` < control-plane registry. A warning is logged when a higher-priority source shadows a plugin declaration.
77
+
78
+ Use plugin-declared MCP servers only when the provider has non-standard auth or when co-locating with custom nodes for the same provider. For standard OAuth/API-key providers, prefer the control-plane registry.
79
+
80
+ ## WorkflowTestKit
81
+
82
+ ```ts
83
+ import { WorkflowTestKit } from "@codemation/core/testing";
84
+ // For defineNode packages:
85
+ import { registerDefinedNodes } from "@codemation/core/testing";
86
+ registerDefinedNodes([myNode]);
87
+ // Then use runNode(...) or run(...) for fuller graph tests.
88
+ ```
89
+
90
+ ## Binary payloads — never put bytes on item.json
91
+
92
+ ```ts
93
+ // Inside execute(items, ctx) when a node fetches binary content:
94
+ const stored = await ctx.binary.attach({
95
+ name: "report.pdf",
96
+ body: Buffer.from(bytes),
97
+ mimeType: "application/pdf",
98
+ filename: "report.pdf",
99
+ });
100
+ const enriched = ctx.binary.withAttachment(item, "report.pdf", stored);
101
+ ```
102
+
103
+ Only the `BinaryAttachment` reference (id, storageKey, mimeType, size) belongs on the item — not the bytes.
104
+
105
+ ## Publishing
106
+
107
+ - `package.json#codemation.plugin` must point at `./dist/codemation.plugin.js`.
108
+ - Do not rely on consumers TypeScript-loading plugin files from `node_modules`.
109
+ - Treat the plugin as a normal npm package: install it in a Codemation app for auto-discovery.
110
+
111
+ ## Anti-patterns
112
+
113
+ - Do not put plugin registration logic inside workflow files — use `codemation.plugin.ts`.
114
+ - Do not ship source-only plugin entries as runtime dependencies — publish `dist/**`.
115
+ - Do not declare an MCP server in a plugin for standard OAuth/API-key providers already in the control-plane registry.