# `Sake.Server`
[🔗](https://github.com/hattoriai/sake/blob/v0.4.3/lib/sake/server.ex#L1)

The server module lists the components and their scopes.

    defmodule MyApp.MCP do
      use Sake.Server, name: "myapp", version: "1.0.0", instructions: "..."
      scope "issues:read", "Read issues"
      tools [MyApp.MCP.SearchIssues]
      resources [MyApp.MCP.Issue]
      prompts [MyApp.MCP.Triage]
    end

Options: `name`, `version` (required), `instructions`, `ttl` (default
300 000 ms), `cache_scope` (`:public` or `:private`; default: private
when the endpoint has authorization, public otherwise), `page_size`
(default 100), `extensions` (a map for extension negotiation),
`authentication` (how the person must have signed in to call a tool,
read a resource or get a prompt of this server, see below).

On the modern protocol, list and read results carry `ttlMs`: the
server's `ttl`, or less. A tool, resource or prompt with its own `ttl:`
shortens the `ttlMs` of every list page that includes it, and a
resource's `ttl:` also sets the `ttlMs` of its `resources/read` result
(the shortest ttl always wins).

`middleware event, plugs` runs host code around the server's calls
(see `Sake.Middleware`); declare it once or more per event, and the
plugs run in the order declared:

    middleware :before_call, [MyApp.MCP.Audit, {MyApp.MCP.Tenant, field: :org_id}]

`mount server, opts` makes another server's tools, resources and prompts
this server's, so that each team or context can own its part of a large
server:

    mount MyApp.MCP.Billing, prefix: "billing", scope: "billing"

With `prefix:`, tool and prompt names take the prefix and an underscore
(`billing_create_invoice`) and resource URIs take it as the first
segment after the scheme (`invoice://billing/{id}`, `ui://billing/board`);
`scope:` (one or many) adds required scopes to every component mounted.
`only:` or `except:` (a list of the mounted server's components, each a
module, a tool or prompt name, or a resource URI, as that server
declares it) mounts some of them:

    mount MyApp.MCP.Billing, prefix: "billing", except: [MyApp.MCP.Billing.Refund]

See `guides/composing.md` for what the mounted server's own middleware,
instructions, scopes and settings become. A `Sake.Proxy` mounts as any
server does, with the components of its upstream.

## Step-up authentication

A tool, resource or prompt with `authentication: [acr: ["mfa"],
max_age: 300]` needs a token whose person signed in with one of those
authentication context classes (`acr`), at most that many seconds ago
(`max_age`), either optional (RFC 9470). The server's own
`authentication:` applies to all its components, its mounted servers'
too: an `acr` must then be among both lists, and the shorter `max_age`
wins. A token that does not meet it is refused with a 401 whose
`insufficient_user_authentication` challenge carries `acr_values` and
`max_age`, for the client to have the person sign in again; a token
that lacks the component's scopes as well gets that challenge, naming
the scopes too, so that one new grant covers both. The components stay
in the lists, and a request without a token (an endpoint without
`auth:`, stdio) is not gated, as for scopes. A requirement that
depends on the arguments is a middleware's: see
`Sake.Middleware.require_authentication/2`. `max_age: 0` means a
sign-in within the last minute. It gates a tool call, a resource read
and a prompt get; lists, completions, subscriptions and the requests
that follow a task (which was checked when it started) are not.

# `allowed?`

```elixir
@spec allowed?(struct(), Sake.Context.t()) :: boolean()
```

Whether the request may see or call the component: no token means no gating.

# `capabilities`

```elixir
@spec capabilities(module()) :: map()
```

# `middleware`
*macro* 

# `mount`
*macro* 

Mounts another server's tools, resources and prompts in this one.
Options: `prefix:`, `scope:`, and `only:` or `except:` (see the module
documentation).

# `notify_list_changed`

```elixir
@spec notify_list_changed(module(), :tools | :resources | :prompts) :: :ok
```

Tells listening clients that the list of tools, resources or prompts changed.

# `prompt`

```elixir
@spec prompt(module(), String.t(), Sake.Context.t() | nil) ::
  {:ok, Sake.Prompt.Spec.t()} | :error
```

The prompt named `name`; see `tool/3`.

# `prompts`
*macro* 

# `prompts`

```elixir
@spec prompts(module(), Sake.Context.t()) :: [Sake.Prompt.Spec.t()]
```

The server's prompts as the request sees them; see `tools/2`.

# `resource`

```elixir
@spec resource(module(), String.t(), Sake.Context.t() | nil) ::
  {:ok, Sake.Resource.Spec.t(), map()} | :error
```

The resource `uri` names, and the template's parameters: one of the
server's own, or, with the request's context, one of its proxies'. A
proxy serves what its upstream lists, and any other URI under its
mount's prefix (a resource link in a proxied result, say), which its
upstream answers for.

# `resource_updated`

```elixir
@spec resource_updated(module(), String.t()) :: :ok
```

Tells subscribed clients that a resource changed.

# `resources`
*macro* 

# `resources`

```elixir
@spec resources(module(), Sake.Context.t()) :: [Sake.Resource.Spec.t()]
```

The server's resources as the request sees them; see `tools/2`.

# `scope`
*macro* 

# `tool`

```elixir
@spec tool(module(), String.t(), Sake.Context.t() | nil) ::
  {:ok, Sake.Tool.Spec.t()} | :error
```

The tool named `name`: one of the server's own (`tool/2`), or, with the
request's context, one its proxies list for the request (`tools/2`).

# `tools`
*macro* 

# `tools`

```elixir
@spec tools(module(), Sake.Context.t()) :: [Sake.Tool.Spec.t()]
```

The server's tools as the request sees them: its own and its mounted
servers', then those its proxies (`Sake.Proxy`) list for the request's
principal. A proxied tool whose name is already taken is left out: an
upstream never shadows a local component.

---

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