The Model Context Protocol (MCP) is an open standard that lets AI assistants use external tools.
Placet ships an MCP server (@placet/mcp) that exposes all Placet capabilities — sending messages, requesting human reviews, rendering diagrams, and more — as MCP tools.
This is the recommended connection type when your agent runs inside an AI-powered IDE or coding assistant like Claude Code, VS Code Copilot, Cursor, or Windsurf.
Transport Modes
The MCP server supports two transport modes:
| Mode | Use Case | Auth |
|---|
| StreamableHTTP (default) | Remote/Docker deployment, multi-client | x-api-key header per request |
| stdio | Local development, single client | PLACET_API_KEY env var |
Setup
Docker (recommended)
The MCP server is included in the default docker-compose.yml:
mcp-server:
container_name: placet-mcp-server
build:
context: .
dockerfile: packages/mcp-server/Dockerfile
environment:
PLACET_API_URL: http://backend:3001
MCP_PORT: 3002
ports:
- '3002:3002'
Start it alongside the rest of Placet:
npx (local / stdio)
For local development or one-off usage:
PLACET_API_URL=http://localhost:3001 \
PLACET_API_KEY=hp_your-api-key \
npx @placet/mcp --stdio
Client Configuration
VS Code / GitHub Copilot
Create .vscode/mcp.json in your project:
{
"servers": {
"placet": {
"type": "http",
"url": "http://localhost:3002/mcp",
"headers": {
"x-api-key": "hp_your-api-key"
}
}
}
}
Claude Code
claude mcp add placet \
--transport http \
--url http://localhost:3002/mcp \
--header "x-api-key: hp_your-api-key"
Or add to ~/.claude/claude_desktop_config.json:
{
"mcpServers": {
"placet": {
"command": "npx",
"args": ["@placet/mcp", "--stdio"],
"env": {
"PLACET_API_URL": "http://localhost:3001",
"PLACET_API_KEY": "hp_your-api-key"
}
}
}
}
Cursor
Add to Cursor settings (Settings > MCP Servers):
{
"placet": {
"url": "http://localhost:3002/mcp",
"headers": {
"x-api-key": "hp_your-api-key"
}
}
}
Windsurf
Add to ~/.codeium/windsurf/mcp_config.json:
{
"mcpServers": {
"placet": {
"serverUrl": "http://localhost:3002/mcp",
"headers": {
"x-api-key": "hp_your-api-key"
}
}
}
}
Any stdio-compatible client
For clients that support stdio transport:
{
"mcpServers": {
"placet": {
"command": "npx",
"args": ["@placet/mcp", "--stdio"],
"env": {
"PLACET_API_URL": "http://localhost:3001",
"PLACET_API_KEY": "hp_your-api-key",
"PLACET_DEFAULT_CHANNEL": "your-channel-id"
}
}
}
}
Set PLACET_DEFAULT_CHANNEL to make the channelId parameter optional in all tools. This is
useful when your agent only works with a single channel.
Channel Management
| Tool | Description |
|---|
list_channels | List all channels accessible by the API key |
create_channel | Create a new channel with name, description, and optional webhook URL |
Messages
| Tool | Description |
|---|
send_message | Send an informational message with markdown and optional status indicator (info, success, warning, error) |
get_messages | List messages with pagination, search, and filtering |
get_message | Get a single message including review status and attachments |
delete_message | Delete (retract) a message |
Reviews (Human-in-the-Loop)
| Tool | Description |
|---|
send_review_message | Send a message that requires human interaction (see review types below) |
wait_for_review | Long-poll for a human response (default 5 min, retryable) |
get_pending_reviews | List all pending reviews in a channel |
Status
| Tool | Description |
|---|
ping_status | Report agent heartbeat — shown as online indicator in the dashboard |
Plugins
| Tool | Description |
|---|
list_plugins | List all installed plugins and their capabilities |
Plugin tools are registered dynamically at startup. The MCP server fetches all installed plugin manifests from the backend and creates a send_{plugin_name}_message tool for each plugin that has an inputSchema. See Dynamic Plugin Tools below.
Review Types
The send_review_message tool supports 5 review types. The AI agent sends the review, and a human responds in the Placet dashboard.
Approval
Show buttons for the human to approve or reject an action.
{
"reviewType": "approval",
"reviewPayload": {
"options": [
{ "id": "approve", "label": "Approve", "style": "primary" },
{ "id": "reject", "label": "Reject", "style": "danger" }
],
"allowComment": true
}
}
Button styles: primary (green), danger (red), secondary (gray), ghost (outline)
Response: { "selectedOption": "approve", "comment": "Looks good!" }
Selection
Let the human choose from a list of options.
{
"reviewType": "selection",
"reviewPayload": {
"mode": "single",
"items": [
{ "id": "opt-a", "label": "Option A", "description": "First choice" },
{ "id": "opt-b", "label": "Option B", "description": "Second choice" }
]
}
}
Set mode to "multi" to allow selecting multiple items.
Response: { "selectedIds": ["opt-a"] }
Render a structured form with typed fields.
{
"reviewType": "form",
"reviewPayload": {
"fields": [
{ "name": "serverName", "type": "text", "label": "Server Name", "required": true },
{
"name": "region",
"type": "select",
"label": "Region",
"options": [
{ "value": "eu-west-1", "label": "EU West" },
{ "value": "us-east-1", "label": "US East" }
]
},
{ "name": "instances", "type": "number", "label": "Instances", "min": 1, "max": 10 },
{ "name": "enableSSL", "type": "checkbox", "label": "Enable SSL", "defaultValue": true },
{ "name": "goLive", "type": "date", "label": "Go-Live Date" },
{ "name": "notes", "type": "textarea", "label": "Notes", "placeholder": "Any details..." }
],
"submitLabel": "Deploy"
}
}
Supported field types: text, number, email, url, textarea, select, checkbox, date, time, datetime, range, password
Field options: required, placeholder, defaultValue, min, max, step, unit, options (for select)
Response: { "serverName": "prod-api-02", "region": "eu-west-1", "instances": 3, "enableSSL": true, ... }
Text Input
Free text input, optionally with a markdown editor.
{
"reviewType": "text-input",
"reviewPayload": {
"markdown": true,
"placeholder": "Your response...",
"prefill": "## Template\n\n",
"minLength": 10,
"maxLength": 5000
}
}
Response: { "text": "The user's response text..." }
Pass-through for custom plugin UIs. See Dynamic Plugin Tools.
The MCP server discovers installed plugins at startup and registers a tool for each one. For example, the built-in plugins create these tools:
send_kroki_diagram_message
Render diagrams (Mermaid, PlantUML, D2, Graphviz, etc.) as SVG via a Kroki server.
{
"pluginData": {
"type": "mermaid",
"source": "graph TD\n A[Start] --> B[End]"
}
}
Supported diagram types: mermaid, plantuml, d2, graphviz, ditaa, erd, nomnoml, svgbob, vega, vegalite, wavedrom, bytefield, excalidraw
Render a pre-filled form and submit to a webhook.
{
"pluginData": {
"name": "John Doe",
"email": "john@example.com",
"message": "Access request for the staging environment"
}
}
When you install additional plugins with an inputSchema, the MCP server automatically creates
new send_{plugin}_message tools — no code changes required.
Workflow Pattern
The typical MCP workflow is fire → poll → continue:
The wait_for_review tool holds the connection for up to 5 minutes (configurable via MCP_CONNECTION_TIMEOUT_MS), polling the backend every 30 seconds. If the human hasn’t responded, it returns status: "timeout" — the agent can call wait_for_review again to keep waiting.
Some MCP clients (like VS Code) have their own HTTP timeouts that may be shorter than the
configured wait time. If waitInline=true fails, use the two-step pattern: send_review_message
followed by wait_for_review.
Environment Variables
| Variable | Default | Description |
|---|
PLACET_API_URL | (required) | Placet backend URL (e.g. http://localhost:3001) |
PLACET_API_KEY | — | API key (required for stdio mode, optional for HTTP mode) |
PLACET_DEFAULT_CHANNEL | — | Default channel ID, makes channelId optional in all tools |
MCP_PORT | 3002 | HTTP transport listen port |
MCP_PATH | /mcp | HTTP transport endpoint path |
MCP_CONNECTION_TIMEOUT_MS | 300000 | Max time wait_for_review holds a connection (5 min) |
MCP_TRANSPORT | — | Set to stdio as alternative to --stdio flag |