# `DDD.MCP`
[🔗](https://github.com/blackuprise/vicander/blob/v0.1.1/lib/ddd/mcp.ex#L1)

The application as a [Model Context Protocol](https://modelcontextprotocol.io) server: an AI
client can call its commands and queries as tools and read its aggregates as resources.

This module is the protocol core. It takes one decoded JSON-RPC message and returns the reply,
so a transport (`DDD.MCP.Stdio`, or an HTTP Plug later) only moves JSON. Use it through a
server module (`DDD.MCP.Server`).

## What is exposed

  * **Tools.** Each listed command and query is a tool. Its input schema is built from the
    command's fields (`DDD.MCP.Schema`), its description from `description "..."`. Queries are
    marked `readOnlyHint: true`.
  * **Resources.** Each listed aggregate is read-only: `name://<identity>` reads one, and
    `name://by/<field>/<value>` runs a `find_by` the repository port declares (at most 100
    results). `resources/list` is empty on purpose: a client is never handed a whole table.

## What a client is told about failures

A **business** error (validation, not found, a precondition) is returned with its code,
message and violations, so the client can correct itself. An **infrastructure** error is a
generic "the operation failed" and the details only go to the log. A malformed request gets a
JSON-RPC error saying what was wrong.

A read-only server refuses every command tool. An `:authorize` function is called before
every tool call and resource read and may refuse it.

# `handle`

```elixir
@spec handle(DDD.MCP.Registry.t(), term()) :: {:reply, map()} | :noreply
```

Handle one decoded JSON-RPC message: `{:reply, response}` or `:noreply` (notifications).

# `parse_error`

A parse-error response, for a transport that received text that is not JSON.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
