Skip to main content
nestrs-mcp is the Model Context Protocol server for the nestrs framework. It exposes project structure, live runtime state, scaffolding actions, and docs search to MCP-aware clients (Claude Code, Cursor, VS Code, Codex CLI), plus the protocol surfaces beyond tools — prompts, resources, completion, elicitation, and tasks. The narrative guide — install, client wiring for each editor, live-runtime setup, embedding recipes — lives on the Connect an AI editor to your nestrs project page. This page is the API reference.

Features

Crate layout

Root re-exports (note the paths that are not at the root):

CLI

The nestrs-mcp binary runs as either a server (no subcommand, with a --transport flag) or as a setup wizard (init / setup subcommand). --transport defaults to stdio; --http-addr defaults to 127.0.0.1:7777.
The wizard’s own flags (--yes, --no-interactive, --transport, --http-addr, --start-http-server) are documented in the setup wizard section of the guide.

NestrsMcpServer

The top-level rmcp ServerHandler. The binary serves this type; embedders construct it directly.
The ServerHandler impl provides get_info (server name nestrs-mcp, version from Cargo), the full surface set (list_prompts, get_prompt, list_resources, list_resource_templates, read_resource, complete), subscriptions (accepted_subscription_filter, listen), and the task RPCs (get_task, update_task, cancel_task).
The wrapper’s #[tool_router] impl block stays empty (rmcp routers are invariant in the handler type). list_tools / get_tool / call_tool dispatch to the four area handlers, so a tools/list against the stock binary returns the full 24-tool surface. Embedding a single area handler is still supported — see Embedding in another binary.
SubServers bundles the four handlers:

Tool surface

Tools are declared with rmcp’s #[tool_router] / #[tool] macros — there is no manual registration API. The pattern every built-in handler follows:
A Json<T> return (where T: Serialize + schemars::JsonSchema) stamps an outputSchema on the tool declaration and lands the typed value in structuredContent — plus a text fallback block for clients that only render text.

Introspection (read-only, read_only_hint = true) — IntrospectionTools

Every tool takes workspace_path: String (absolute path to the workspace root — the directory containing Cargo.toml) so one server instance can serve multiple projects over a long session.

Runtime — RuntimeTools

Each tool takes an AdminEndpoint: {base_url: String, token: Option<String>} (e.g. "http://127.0.0.1:7777"). No Cargo feature required — but the target app must have the admin feature and use_admin(...) enabled. Backed by the AdminClient.

Scaffolding (write actions, destructive_hint = true) — ScaffoldTools

fields is Vec<DtoFieldSpec> — {name, ty, optional?, validators?} per field (see Scaffold API). All write actions return a ScaffoldReport — {files_created: [..], files_modified: [..]} — so the model can show the user exactly what changed. Guards: module and DTO names must be valid Rust idents (is_safe_ident), and project names must be valid crate names; there is no workspace-containment check on path, so treat tool output paths as trusted input.

Docs search (read-only, read_only_hint = true) — DocsTools

The index is built lazily on first use per workspace_path and cached for the process lifetime.

Protocol surfaces: McpSurfaces

Clone-cheap bundle of the non-tool protocol surfaces, carried by NestrsMcpServer (attach with .with_surfaces(...)).
Handler type aliases (for annotation or building your own):
Matching rules: resources/read checks the static resource map first (a static resource beats a matching template); templates match on their static prefix (everything before the first {, trailing / trimmed). Subscriptions use subscriptions/listen on protocol ≥ 2026-07-28 with the legacy subscribe/unsubscribe kept for older peers.

CacheHints (SEP-2549)

Hints are stamped as top-level ttlMs / cacheScope fields on list_prompts, list_resources, list_resource_templates, and read_resource results — suppressed for peers below protocol 2026-07-28.

Message helpers

Elicitation

MRTR for tools (SEP-2322) — available without any feature. A tool returns an InputRequired result instead of an error:
The elicitation rides under a single server-assigned key ("input"); the client echoes its response back under the same key. Server→client elicitation (SEP-1034) — behind the elicitation feature. Register one handler via McpSurfaces::register_elicitation, then call the wrapper from a tool body:
elicit probes the client’s capabilities first and returns ElicitationAction::Cancel (rather than an error) if the client didn’t advertise elicitation.

Tasks (SEP-2663)

io.modelcontextprotocol/tasks. The TaskManager store always exists; .with_task_support() only advertises the extension (undeclared, the SDK rejects tasks/get|update|cancel with -32601 before the handler runs). Inside a tool body, spawn an operation and return CallToolResponse::Task(CreateTaskResult::new(task)):

Per-tool-call authorization (authz)

With a data context attached, NestrsMcpServer’s call_tool override opens a TransactionSlot per call, installs the ability + principal + request scope, dispatches, post-masks the response with nestrs::mask_value (the same walker HTTP/WS/GraphQL use; error results are never masked), then commits on success / rolls back on tool error. Task-local accessors for tool bodies:
Pipeline helpers (what the override calls; also usable directly in tests):

AdminClient

HTTP client for a running nestrs app’s admin sidecar (reqwest + rustls-tls, 5-second timeout, no retries).
Wire types (nestrs_mcp::runtime):
The app side: nestrs = { features = ["admin"] } + NestApplication::use_admin(AdminOptions { addr, token }), then tokio::spawn(handle.serve()). Token auth is Authorization: Bearer <token> header-only (query-string tokens are rejected); with no token the listener is loopback-only and 401s everything.

Introspection API

Source-level parsing, independent of a running app:
Summary types (introspection::source):
DTO metadata (introspection::metadata):
The parser is strictly additive: unknown attributes become ParserWarnings, never parse failures.

Scaffold API

Docs search API

Wizard API

Error type

Error conventions

Tool bodies return Result<Json<...>, rmcp::ErrorData>:
  • Operational failure (operation ran but failed — file not found, parse error, app not reachable, scaffold failure): Err(ErrorData::internal_error(msg)) — the message is visible to the model, which can read it and recover.
  • Bad parameters (unknown module / controller / provider / DTO / route name): Err(ErrorData::invalid_params("module x not found")).
  • Success: a Json<T> payload — typed value in structuredContent (with an outputSchema stamped from the return type) plus a text fallback block.

Embedding in another binary

nestrs-mcp is a library as well as a binary. Each area handler is a standalone ServerHandler, so you can serve any subset without spawning a subprocess:
rmcp is not re-exported — depend on it directly (rmcp = { version = "3.1", default-features = false, features = ["server", "transport-io"] }, plus transport-streamable-http-server for HTTP). The nestrs-cli Cargo manifest carries nestrs-mcp as an optional dependency behind its mcp feature (mcp = ["dep:nestrs-mcp", "nestrs-mcp/admin"]) so a future nestrs-cli mcp subcommand can serve the full tool set in-process — the dependency is stubbed (off by default, no subcommand yet), so existing CLI builds are unaffected.