Plane docs
SDK and CLI

@plane/sdk

Four layers, each usable on its own.

npm i @plane/sdk
ImportWhat it gives you
@plane/sdk/clientThe Plane API as ordinary promises.
@plane/sdk/verifyProof that an incoming request really came from Plane.
@plane/sdk/browserA resuming SSE reader, and one layer per stream format.
@plane/sdk/devThe outbound channel client. Behind npx plane dev.
@plane/sdkCo-definition: definePlane, tool, providerTool, handlers, sync.

Everything on the public surface is plain TypeScript. Effect is not a dependency; zod v4 is a peer dependency for tool input schemas.

The root export

definePlane is the whole point of the package: the agent definition and the code its tools run, in one object, so neither half can drift from the other. It is covered in its own guide.

import { definePlane, tool, providerTool, createPlaneClient } from "@plane/sdk"

export const plane = definePlane({ agent: { … }, tools: [ … ], hooks: { … } })

plane.definition()               // the definition, without talking to Plane
plane.handlers                   // { GET, POST, DELETE } — Web Request/Response
await plane.sync({ publicUrl })  // connections.upsert + agents.upsert
await plane.sessions.start({ message, metadata, identity, overrides })
plane.sessions.stream(id)        // async iterable of SessionEvent
await plane.sessions.children(id)
await plane.approvals.pending(sessionId)
await plane.approvals.allow(sessionId, toolCallId, { actor })
await plane.approvals.deny(sessionId, toolCallId, { message })
await plane.authorizations.pending(sessionId)
await plane.dev({ planeUrl, name })

The client is generated

Plane's API is an OpenAPI 3.1 document, itself generated from the contract the server implements. This package's transport is generated from that, with openapi-typescript for the types and openapi-fetch — about two kilobytes — for the runtime. Every path the client names is checked against the document at compile time, so an endpoint renamed upstream is a build failure here rather than a 404 in your logs.

What is not generated is the shape of client.agents.create(...). A generated client's ergonomics are the generator's opinion; the namespaces, the option objects, the PlaneError subclasses and the async-iterable stream are hand-written over a generated transport.

A client in another language comes from the same document and nothing else — see Generating your own client.

Notes and limits

  • The MCP server is stateless and built per request. A tool handler needs the verified claims of the request it is answering, so the server closes over exactly one verified context.
  • A handler's return value is JSON-serialised into the MCP result. Return { content: [...] } to speak MCP directly — rich blocks, isError.
  • verify: { enabled: false } exists for local development against a fake Plane. An endpoint with verification off is an open tool-execution endpoint. Never ship it.

On this page