build-on-vibekit
Extend VibeKit from its source workspace. Use when defining VibeKit tools, building a ToolPlugin package, composing a deployment, or exposing a custom deployment through stdio or HTTP MCP. Covers the current packages/vibekit/examples and packages/vibekit/src/plugins/* patterns. D
Install
npx skills add https://github.com/initlabsai/vibekit/tree/main/skills/build-on-vibekit
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install initlabsai-vibekit@llmmart
git clone https://github.com/initlabsai/vibekit.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole initlabsai/vibekit collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Build on VibeKit
VibeKit exposes one ToolDefinition contract through every host. Extend that
contract, compose tools and plugins into a deployment, then select a host. Do
not create a parallel handler or execution path.
The toolkit surface
Beyond tools and plugins, @initlabs/vibekit ships the pieces the web agent is
built from — reach for these before writing your own: @initlabs/vibekit/agent
(createAgent, createAgentHandler: a turn over HTTP as NDJSON), /actions
(the draft → approve → sign → confirm machine, createWalletSignDraft), /pay
(createPaywall: x402 → credit → charge(request)), /rest
(createRestHandler: POST /tools/<tool>), and vibekit add <component>
(copy-paste React whose props are a tool's output type). Runnable examples:
packages/vibekit/examples/{agent-http,rest,signer,stdio,http}.ts and
packages/vibekit/examples/action.ts.
Current distribution boundary
Everything ships as one package, @initlabs/vibekit, with subpath exports
(. is the core contract; ./tools, ./preset, ./mcp, ./agent,
./signer-keystore, ./plugins/<name>). Build against this monorepo using
its workspace:* dependency. Do not invent install, publish, or versioning
instructions for external consumers.
Before changing structure, read the repository AGENTS.md and
docs/CONSTITUTION.md. Ask before adding a dependency, package, app, registry, or
extension point.
Choose the guide
| Task | Guide |
|---|---|
| Select tools and plugins, configure networks or signing, and expose a custom stdio or HTTP MCP | Custom MCP deployment |
| Define tools, integrate an external service, and package them as a reusable plugin | Plugin authoring |
Load only the guide needed for the current task. A custom MCP may consume an existing plugin; plugin work does not require changing a host.
Non-negotiable contracts
- Define every tool with
defineTool()and give every parameter a Zod schema and useful.describe()text. - Tool handlers receive all runtime state through
ToolContext. Do not keep module-level mutable state or mutate the context. - Throw
ToolErrorwith a stable code for expected failures. Never return an{ error }result from a handler. - Describe the post-
jsonSafewire shape inoutput: bigint values become numbers or decimal strings and bytes become base64. - Every host must execute tools through
executeToolCall; use the existing MCP adapter rather than registering bespoke handlers. - Build writes through
packages/vibekit/src/core/compose/. Stop if a write requires a side path around that engine. - Keep tool results structured. Tools do not return JSX, HTML, or terminal markup.
- Land tests with code. Run the affected package tests and typecheck, then the
repository gate required by
AGENTS.md.
Source map
packages/vibekit/src/core/contract.ts—ToolDefinition,ToolContext, andToolPluginpackages/vibekit/src/core/deployment.ts— registry validation, network contexts, andexecuteToolCallpackages/vibekit/src/mcp/— the generic ToolDefinition-to-MCP adapterpackages/vibekit/src/preset/— the stock mix (default tools, default plugins, keystore tools, NETWORK env convention) the stock hosts compose frompackages/vibekit/examples/— the reference stdio and HTTP deployments, typechecked with the packagepackages/vibekit/src/plugins/nfd/and.../pera/— service-backed plugin examples with output schemas, network guards, and tests
Files (vibekit)
-
references
-
custom-mcp.md 5.1 KB
# Custom MCP deployment Use `packages/vibekit/examples/` as the executable reference. VibeKit uses `@modelcontextprotocol/server` v2 and the MCP `2026-07-28` stateless protocol. A deployment is configuration: a set of tools, optional plugins, served networks, compose or execute mode, and an optional signer. The MCP package adapts that deployment to a transport. The two standard transports remain distinct deployment choices: - stdio is a local, client-launched subprocess. One server instance lives for that process-scoped connection. - Streamable HTTP is the remote transport. Every message is its own POST and every request gets a fresh MCP server instance. Do not add an initialize handshake, `Mcp-Session-Id`, GET event stream, or session affinity. Protocol statelessness does not prohibit pooled network clients or service caches. It prohibits hidden client-session state. If an operation must carry application state across calls, return an explicit opaque handle and require the next tool call to pass it back. ## Work within the current boundary Copy a file from `packages/vibekit/examples/` into your own entry point; do not add a new app to this monorepo without owner approval. Apps are independent deployment units, import only public `@initlabs/*` exports through `workspace:*`, and never use relative imports into packages. Packages must never depend on an app. Keep one shared definition of the tool and plugin mix. The stock mix lives in `@initlabs/vibekit/preset`: `defaultTools` (every domain), `defaultPlugins()`, `withKeystoreTools()`, and `networksFromEnv()`; the CLI hosts and the reference app compose from it. A custom deployment that wants a different mix composes its own arrays the same way — extract one plain options factory rather than copying the mix between entry points. ## Select the deployment Pass these fields to the host adapter: - `name` and optional `version` identify the MCP server. - `network` is the default `NetworkId` or custom `NetworkConfig`. - `networks` optionally serves more networks. VibeKit injects the `network` argument into tool schemas automatically; it is required for writes. - `mode` is `compose` or `execute`. - `tools` is an array of `ToolDefinition`s. - `plugins` is an array of instantiated `ToolPlugin`s. - `resolveSigner` is required when `mode` is `execute`. - `readFile` grants tools local file reads (the `appSpecPath` parameter). Pass `readLocalFile` from `@initlabs/vibekit/preset` on a local host; leave it unset on a remote one, so a path in a tool call cannot read the server's files (the tool answers `APP_SPEC_PATH_UNAVAILABLE`). Registry validation happens at startup. Duplicate plugin names, duplicate tool names, and execute mode without a signer are configuration errors; do not defer or suppress them. Start in `compose` mode unless the deployment owns an appropriate signer. Compose mode returns unsigned transaction groups for external signing. Execute mode signs and sends through `resolveSigner` and must preserve the host's approval boundary. ## Stdio host Stdio is the local-agent path: ```ts import { serveMcpStdio } from "@initlabs/vibekit/mcp/stdio"; import { accountQueries, networkQueries } from "@initlabs/vibekit/tools"; const handle = serveMcpStdio({ name: "my-vibekit-mcp", network: "testnet", mode: "compose", tools: [...networkQueries, ...accountQueries], plugins: [], }); process.on("SIGINT", () => void handle.close()); ``` Write operational messages to stderr. Stdout belongs to the MCP transport. Close the host and any signer or service resources during shutdown. For execute mode, follow `packages/vibekit/examples/stdio.ts`: create the signer, add any signer-dependent tools, pass `resolveSigner`, and close the signer on exit. Do not expose mnemonic or seed material to a tool handler. ## Stateless Streamable HTTP host The HTTP adapter returns a `2026-07-28` stateless fetch handler. Its server factory is invoked once per request: ```ts import { createMcpHttpHandler } from "@initlabs/vibekit/mcp/http"; import { accountQueries, networkQueries } from "@initlabs/vibekit/tools"; const handler = createMcpHttpHandler({ name: "my-vibekit-mcp", network: "testnet", mode: "compose", tools: [...networkQueries, ...accountQueries], }); Bun.serve({ port: 8788, fetch: (request) => handler.fetch(request) }); ``` The current adapter also accepts 2025-era clients through a stateless compatibility path. It does not create or retain protocol sessions. Keep public HTTP deployments in compose mode. Execute mode over HTTP is an explicit self-hosting choice and requires authentication and an approval model in front of the handler; the adapter does not provide those controls. Validate the `Origin` header before forwarding requests. Bind local servers to `127.0.0.1`; public deployments need an explicit origin policy and authentication at the application or gateway boundary. ## Verify From the repository root: ```bash bun run --cwd packages/vibekit typecheck bun run mcp ``` Exercise startup with the intended environment and confirm the client sees only the selected tools, plugins, and networks. Add focused tests when wiring contains logic beyond declarative options. -
plugin-authoring.md 4.6 KB
# Plugin authoring A plugin factory returns a `ToolPlugin`: a unique name, a tool array, and optionally a service and semantic view schemas. The deployment puts the service at `ctx.services[plugin.name]` and combines the plugin's tools with its base tools. Use the nearest existing package as a pattern: - `packages/vibekit/src/plugins/pera` — small HTTP service, output shaping, network guard, semantic view, and fake-service tests - `packages/vibekit/src/plugins/nfd` — per-network client cache and normalization of unusual SDK failures - `packages/vibekit/src/plugins/alpha-arcade` — configured factory options and a larger SDK integration ## Plugin shape A plugin is a directory in the one published package: source in `packages/vibekit/src/plugins/<name>/` with an `index.ts`, tests in `packages/vibekit/test/plugins/<name>/`, and a `./plugins/<name>` entry in the `exports` map of `packages/vibekit/package.json`. Add one only when there is a current named consumer and owner approval. The package declares `algosdk` and `zod` as peers; import core from `@initlabs/vibekit` and tools from its subpaths. A third-party SDK the plugin wraps is an optional peer dependency of the package (declared in `peerDependencies` and `peerDependenciesMeta`, installed as a devDependency for the workspace, and listed in the README's subpath table), so only consumers of that subpath install it. Ask before adding any dependency. ## Implement the service boundary Put stateful clients, caches, credentials, and remote calls behind a service created by the plugin factory. Do not keep them in module-level mutable state. Use a typed accessor that reads `ctx.services[PLUGIN_NAME]` and throws `ToolError('PLUGIN_NOT_CONFIGURED', ...)` when the plugin is absent. Validate network support at that accessor or service boundary and throw a stable `UNSUPPORTED_NETWORK` error before calling an incompatible upstream. Normalize third-party failures into user-safe `ToolError`s when the SDK does not throw ordinary `Error` objects. ```ts import { defineTool, ToolError, type ToolContext, type ToolPlugin, } from "@initlabs/vibekit"; import { z } from "zod"; const PLUGIN_NAME = "example"; interface ExampleService { lookup(id: string): Promise<unknown>; } function getExample(ctx: ToolContext): ExampleService { const service = ctx.services[PLUGIN_NAME] as ExampleService | undefined; if (!service) { throw new ToolError( "PLUGIN_NOT_CONFIGURED", "The example plugin is not registered in this deployment", ); } return service; } ``` ## Define structured tools Every tool uses `defineTool()`. Give it a globally unique, action-oriented name; a description that tells the model when to call it; described Zod parameters; and an output schema for the post-`jsonSafe` result. Set `requiresSigner` for tools that spend from a user account. Set `mutatesState` for state changes that do not spend user funds, and `expensive` for unusually large reads. These flags drive host approval annotations. Use a coarse `view` hint such as `table` or `json` unless a trusted semantic Explorer view already exists. A new semantic view is a separate protocol change; do not invent one solely in the plugin. If the view exists, expose its post-`jsonSafe` Zod schema in `plugin.views` under the same namespaced id. ## Return the plugin ```ts export function examplePlugin(options: ExampleOptions = {}): ToolPlugin { const service = createExampleService(options); const tools = [lookupExampleTool]; return { name: PLUGIN_NAME, description: "One-line description for deployment settings", tools, service, }; } ``` Factories make configuration explicit and keep each deployment independent. Do not make importing the module create clients, read environment variables, or perform network calls. ## Register and test Instantiate the plugin in a deployment's `plugins` array. Do not copy its tools into the deployment's base tool list. To ship it in every stock host at once, add it to `defaultPlugins()` in `packages/vibekit/src/preset` — that is the one registration point for the CLI hosts and the reference app; the TUI keeps its own roster in `apps/tui/src/features/agent/session.ts`. Tests should cover: - factory name, tool names, flags, output schemas, and views - missing-registration and unsupported-network errors - handler output shaping with a fake service, without live network calls - upstream edge cases and error normalization - write composition and signer requirements when the plugin writes Run the package gates from the repository root: ```bash bun run --cwd packages/vibekit typecheck bun run --cwd packages/vibekit test ```
-
-
SKILL.md 4.2 KB
--- name: build-on-vibekit description: Extend VibeKit from its source workspace. Use when defining VibeKit tools, building a ToolPlugin package, composing a deployment, or exposing a custom deployment through stdio or HTTP MCP. Covers the current packages/vibekit/examples and packages/vibekit/src/plugins/* patterns. Do not use for routine CLI or on-chain operations inside a VibeKit-initialized project. --- # Build on VibeKit VibeKit exposes one `ToolDefinition` contract through every host. Extend that contract, compose tools and plugins into a deployment, then select a host. Do not create a parallel handler or execution path. ## The toolkit surface Beyond tools and plugins, `@initlabs/vibekit` ships the pieces the web agent is built from — reach for these before writing your own: `@initlabs/vibekit/agent` (`createAgent`, `createAgentHandler`: a turn over HTTP as NDJSON), `/actions` (the draft → approve → sign → confirm machine, `createWalletSignDraft`), `/pay` (`createPaywall`: x402 → credit → `charge(request)`), `/rest` (`createRestHandler`: `POST /tools/<tool>`), and `vibekit add <component>` (copy-paste React whose props are a tool's output type). Runnable examples: `packages/vibekit/examples/{agent-http,rest,signer,stdio,http}.ts` and `packages/vibekit/examples/action.ts`. ## Current distribution boundary Everything ships as one package, `@initlabs/vibekit`, with subpath exports (`.` is the core contract; `./tools`, `./preset`, `./mcp`, `./agent`, `./signer-keystore`, `./plugins/<name>`). Build against this monorepo using its `workspace:*` dependency. Do not invent install, publish, or versioning instructions for external consumers. Before changing structure, read the repository `AGENTS.md` and `docs/CONSTITUTION.md`. Ask before adding a dependency, package, app, registry, or extension point. ## Choose the guide | Task | Guide | | ---------------------------------------------------------------------------------------------- | -------------------------------------------------- | | Select tools and plugins, configure networks or signing, and expose a custom stdio or HTTP MCP | [Custom MCP deployment](references/custom-mcp.md) | | Define tools, integrate an external service, and package them as a reusable plugin | [Plugin authoring](references/plugin-authoring.md) | Load only the guide needed for the current task. A custom MCP may consume an existing plugin; plugin work does not require changing a host. ## Non-negotiable contracts - Define every tool with `defineTool()` and give every parameter a Zod schema and useful `.describe()` text. - Tool handlers receive all runtime state through `ToolContext`. Do not keep module-level mutable state or mutate the context. - Throw `ToolError` with a stable code for expected failures. Never return an `{ error }` result from a handler. - Describe the post-`jsonSafe` wire shape in `output`: bigint values become numbers or decimal strings and bytes become base64. - Every host must execute tools through `executeToolCall`; use the existing MCP adapter rather than registering bespoke handlers. - Build writes through `packages/vibekit/src/core/compose/`. Stop if a write requires a side path around that engine. - Keep tool results structured. Tools do not return JSX, HTML, or terminal markup. - Land tests with code. Run the affected package tests and typecheck, then the repository gate required by `AGENTS.md`. ## Source map - `packages/vibekit/src/core/contract.ts` — `ToolDefinition`, `ToolContext`, and `ToolPlugin` - `packages/vibekit/src/core/deployment.ts` — registry validation, network contexts, and `executeToolCall` - `packages/vibekit/src/mcp/` — the generic ToolDefinition-to-MCP adapter - `packages/vibekit/src/preset/` — the stock mix (default tools, default plugins, keystore tools, NETWORK env convention) the stock hosts compose from - `packages/vibekit/examples/` — the reference stdio and HTTP deployments, typechecked with the package - `packages/vibekit/src/plugins/nfd/` and `.../pera/` — service-backed plugin examples with output schemas, network guards, and tests
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.