Server
Interact with dropstone server over HTTP.
The dropstone serve command runs a headless HTTP server that exposes an OpenAPI endpoint a Dropstone client can use.
Usage
dropstone serve [--port <number>] [--hostname <string>] [--cors <origin>]
Options
| Flag | Description | Default |
|---|---|---|
--port | Port to listen on | 4096 |
--hostname | Hostname to listen on | 127.0.0.1 |
--mdns | Enable mDNS discovery | false |
--mdns-domain | Custom domain name for mDNS service | dropstone.local |
--cors | Additional browser origins to allow | [] |
--cors can be passed multiple times:
dropstone serve --cors http://localhost:5173 --cors https://app.example.com
Authentication
Set DROPSTONE_SERVER_PASSWORD to protect the server with HTTP basic auth. The username defaults to dropstone, or set DROPSTONE_SERVER_USERNAME to override it. This applies to both dropstone serve and dropstone web.
DROPSTONE_SERVER_PASSWORD=your-password dropstone serve
Agent credentials
DROPSTONE_SERVER_PASSWORD protects the server itself. It does not tell the agent how to reach Dropstone. On an unattended machine there is no signed-in account to inherit, so pass an API key through the provider config:
{
"provider": {
"dropstone": {
"options": {
"apiKey": "dsk_live_...",
"baseURL": "https://api.dropstone.io/api/v1"
}
}
}
}
baseURL matters. API keys are accepted at /api/v1, not at /v1, and a key sent to /v1 is rejected with 403 Invalid token format. Please log in again. Set it here rather than through DROPSTONE_BASE_URL, which is also used to build the account, usage, and memory endpoints and will break them if you point it at a versioned path.
Generate a key at dropstone.io/dashboard/settings.
Note
The default build agent asks before every tool call. Nothing here can answer that prompt, so the request hangs rather than failing. Either send "agent": "accept all" or set an explicit permission allowlist. See Permissions.
Sending a prompt
POST /session/:id/message requires both agent and model. Omitting model resolves no default: the turn returns 200 with an empty body and nothing runs.
curl -X POST "http://127.0.0.1:4096/session/$SID/message?directory=$PWD" \
-H "Content-Type: application/json" \
-d '{
"agent": "build",
"model": { "providerID": "dropstone", "modelID": "dropstone-pro" },
"parts": [{ "type": "text", "text": "Add error handling to src/index.ts" }]
}'
A turn that fails still returns 200. The reason is at data.info.error, not at the transport level, so check that field rather than relying on the status code.
How it works
dropstone serve exposes Dropstone's capabilities over an OpenAPI 3.1 HTTP endpoint. The same endpoint is used to generate the SDK.
Use the server when you want to drive Dropstone programmatically: from a script, a CI pipeline, or an integration of your own. The interactive session and the server are independent. Running dropstone serve starts a fresh standalone server regardless of whether you have an interactive session open.
You can override the bind address with the --hostname and --port flags.
Spec
The server publishes an OpenAPI 3.1 spec that can be viewed at:
http://<hostname>:<port>/doc
For example, http://localhost:4096/doc. Use the spec to generate clients or inspect request and response types. Or view it in a Swagger explorer.
APIs
The dropstone server exposes the following APIs.
Global
| Method | Path | Description | Response |
|---|---|---|---|
GET | /global/health | Get server health and version | { healthy: true, version: string } |
GET | /global/event | Get global events (SSE stream) | Event stream |
Project
| Method | Path | Description | Response |
|---|---|---|---|
GET | /project | List all projects | Project[] |
GET | /project/current | Get the current project | Project |
Path & VCS
| Method | Path | Description | Response |
|---|---|---|---|
GET | /path | Get the current path | Path |
GET | /vcs | Get VCS info for the current project | VcsInfo |
Config
| Method | Path | Description | Response |
|---|---|---|---|
GET | /config | Get config info | Config |
PATCH | /config | Update config | Config |
Sessions
| Method | Path | Description | Notes |
|---|---|---|---|
GET | /session | List all sessions | Returns Session[] |
POST | /session | Create a new session | body: { parentID?, title? }, returns Session |
GET | /session/status | Get session status for all sessions | Returns { [sessionID: string]: SessionStatus } |
GET | /session/:id | Get session details | Returns Session |
DELETE | /session/:id | Delete a session and all its data | Returns boolean |
PATCH | /session/:id | Update session properties | body: { title? }, returns Session |
GET | /session/:id/children | Get a session's child sessions | Returns Session[] |
GET | /session/:id/todo | Get the todo list for a session | Returns Todo[] |
POST | /session/:id/init | Analyze app and create AGENTS.md | body: { messageID, providerID, modelID }, returns boolean |
POST | /session/:id/fork | Fork an existing session at a message | body: { messageID? }, returns Session |
POST | /session/:id/abort | Abort a running session | Returns boolean |
GET | /session/:id/diff | Get the diff for this session | query: messageID?, returns FileDiff[] |
POST | /session/:id/summarize | Summarize the session | body: { providerID, modelID }, returns boolean |
POST | /session/:id/revert | Revert a message | body: { messageID, partID? }, returns boolean |
POST | /session/:id/unrevert | Restore all reverted messages | Returns boolean |
POST | /session/:id/permissions/:permissionID | Respond to a permission request | body: { response, remember? }, returns boolean |
Messages
| Method | Path | Description | Notes |
|---|---|---|---|
GET | /session/:id/message | List messages in a session | query: limit?, returns { info: Message, parts: Part[]}[] |
POST | /session/:id/message | Send a message and wait for response | body: { messageID?, model?, agent?, noReply?, system?, tools?, parts }, returns { info: Message, parts: Part[]} |
GET | /session/:id/message/:messageID | Get message details | Returns { info: Message, parts: Part[]} |
POST | /session/:id/prompt_async | Send a message asynchronously (no wait) | body: same as /session/:id/message, returns 204 No Content |
POST | /session/:id/command | Execute a slash command | body: { messageID?, agent?, model?, command, arguments }, returns { info: Message, parts: Part[]} |
POST | /session/:id/shell | Run a shell command | body: { agent, model?, command }, returns { info: Message, parts: Part[]} |
Commands
| Method | Path | Description | Response |
|---|---|---|---|
GET | /command | List all commands | Command[] |
Files
| Method | Path | Description | Response |
|---|---|---|---|
GET | /find?pattern=<pat> | Search for text in files | Array of match objects with path, lines, line_number, absolute_offset, submatches |
GET | /find/file?query=<q> | Find files and directories by name | string[] (paths) |
GET | /find/symbol?query=<q> | Find workspace symbols | Symbol[] |
GET | /file?path=<path> | List files and directories | FileNode[] |
GET | /file/content?path=<p> | Read a file | FileContent |
GET | /file/status | Get status for tracked files | File[] |
/find/file query parameters
query(required): search string (fuzzy match)type(optional): limit results to"file"or"directory"directory(optional): override the project root for the searchlimit(optional): max results (1–200)dirs(optional): legacy flag ("false"returns only files)
LSP, Formatters & MCP
| Method | Path | Description | Response |
|---|---|---|---|
GET | /lsp | Get LSP server status | LSPStatus[] |
GET | /formatter | Get formatter status | FormatterStatus[] |
GET | /mcp | Get MCP server status | { [name: string]: MCPStatus } |
POST | /mcp | Add MCP server dynamically | body: { name, config }, returns MCP status object |
Agents
| Method | Path | Description | Response |
|---|---|---|---|
GET | /agent | List all available agents | Agent[] |
Logging
| Method | Path | Description | Response |
|---|---|---|---|
POST | /log | Write log entry. Body: { service, level, message, extra? } | boolean |
Auth
| Method | Path | Description | Response |
|---|---|---|---|
PUT | /auth/:id | Set authentication credentials for the given target. | boolean |
Events
| Method | Path | Description | Response |
|---|---|---|---|
GET | /event | Server-sent events stream. First event is server.connected, then bus events | Server-sent events stream |
Docs
| Method | Path | Description | Response |
|---|---|---|---|
GET | /doc | OpenAPI 3.1 specification | HTML page with OpenAPI spec |