
@lesto/mcp
by lesto-run
@lesto/mcp
Expose a running Lesto app to AI agents as governed MCP
tools — over stdio for a local agent, or over remote HTTP behind OAuth for an agent on the
other side of the internet. An agent in Claude, Cursor, an editor, or your own
@modelcontextprotocol/sdk client can inspect your routes, read and write content, generate
UI, and drive real requests through the live app — across one audited choke point, with
read-only as the floor and writes behind an explicit grant.
This is the load-bearing half of "agent-native": the agent surface is a first-class, audited part of the framework, not a token you hand a model and hope. Every capability is an operation; the CLI, the UI, and this MCP server are three front-ends over the same operations. An agent can't do anything you couldn't do from the command line — same operations, a different caller.
import { buildTools, dispatch } from "@lesto/mcp";
const tools = buildTools({ app, routes, audit, mode: "operator" });
await dispatch({ app, routes, audit, mode: "operator" }, tools, "list_routes", {});
The tools
buildTools(context) assembles the tool set from your app; dispatch(context, tools, name, input)
finds one by name, audits the call, and runs it. Nine operations today, each carrying a static
destructive flag — and a destructive tool refuses outside operator mode:
| Tool | Kind | |
|---|---|---|
list_routes | read | Every route the running app answers, in resolution order. |
handle_request | destructive | Dispatch a real { method, path, query, headers, body } through the live app and return its response — same routes, same middleware, same database. |
generate_ui | read | A Lesto UI tree from a natural-language prompt (injected; inert when unwired). |
list_content_collections | read | Each content collection with its entry count. |
get_content_entry | read | One entry by collection + slug. |
query_content | read | A collection's entries, optionally capped by a limit. |
create_content_entry | destructive | Author a new content entry. |
update_content_entry | destructive | Merge data into an existing entry, replacing its body. |
delete_content_entry | destructive | Remove an entry by collection + slug. |
Schema migrations are deliberately not on this surface — those stay in code and the CLI.
The content tools depend on @lesto/content-core / @lesto/content-store as optional peers:
the package installs and its generic tools (list_routes, handle_request, generate_ui) run
without them; the six content tools refuse, coded, when the peers aren't wired.
handle_request only forwards an allowlist of identity headers — authorization, cookie,
content-type, accept, accept-language — so an agent can act as a user without being able
to spoof the infrastructure headers the runtime trusts (x-forwarded-for, x-request-id).
Governed at one choke point
Every tool call goes through dispatch, which does two things a hand-rolled "expose an API to
the model" setup does not.
It defaults closed. A server has a mode, and the floor is read-only:
type McpMode = "read-only" | "operator"; // unset → "read-only"
A destructive tool refuses outside operator with an McpError (MCP_OPERATOR_REQUIRED). The
safety property that matters: forget to set the mode and the agent gets the safe surface. You
opt in to letting an agent change things.
It audits everything. The audit sink is mandatory — there is no un-audited path to a tool. Every dispatch, success or failure, known tool or typo, writes one record before the result surfaces:
interface McpAuditRecord {
tool: string;
inputHash: string; // a SHA-256 of the input — never the (possibly sensitive) raw args
outcome: "ok" | "error";
durationMs: number;
actor: string | undefined; // WHO drove it (the resolved principal), or undefi
Related servers

n8n
by n8n-io
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.

@modelcontextprotocol/server-everything
OfficialMCP server that exercises all the features of the MCP protocol

@modelcontextprotocol/server-filesystem
OfficialMCP server for filesystem access