Snodo.Router (snodo v0.1.0)

Copy Markdown View Source

An immutable registry and synchronous protocol-neutral dispatcher.

The router owns no process, connection, session, or application state.

dispatch/5 accepts the immutable execution options the server holds: :schema_validator and the optional :authorization policy. Snodo.Server supplies both from Snodo.Server.Runtime; calling the router directly with neither runs neither.

Summary

Functions

Returns whether any registered prompt or resource template supports completion.

Runs one operation against the registered components.

Returns the definition of every registered prompt, sorted by name.

Returns the definition of every resource template, sorted by URI template.

Returns the definition of every direct resource, sorted by URI.

Returns the definition of every registered tool, sorted by name.

Returns an empty router.

Registers a prompt module under the name in its definition.

Registers a resource module.

Registers a tool module under the name its Snodo.Tool.name/0 returns.

Types

operation()

@type operation() ::
  :tools_list
  | {:tools_call, String.t()}
  | :resources_list
  | :resource_templates_list
  | {:resource_read, String.t()}
  | :prompts_list
  | {:prompt_get, String.t()}
  | :completion_complete
  | term()

t()

@type t() :: %Snodo.Router{
  prompts: %{optional(String.t()) => module()},
  resource_names: %{optional(String.t()) => module()},
  resource_templates: %{optional(String.t()) => module()},
  resources: %{optional(String.t()) => module()},
  tools: %{optional(String.t()) => module()}
}

Functions

completion_capable?(router)

@spec completion_capable?(t()) :: boolean()

Returns whether any registered prompt or resource template supports completion.

dispatch(router, operation, params, context, opts \\ [])

@spec dispatch(t(), operation(), map(), Snodo.Context.t(), keyword()) ::
  {:ok, Snodo.Result.t()} | {:error, Snodo.Error.t()}

Runs one operation against the registered components.

Operations and the params each reads:

  • :tools_list, :prompts_list, :resources_list, and :resource_templates_list - the whole sorted catalog, less any component the authorization policy refuses in the :discovery phase. params is ignored. Pagination and cache hints are applied later by Snodo.Server.
  • {:tools_call, name} - calls the tool with params["arguments"] (default %{}).
  • {:resource_read, uri} - reads the direct resource or the one template that matches uri. Template variables are merged into params before Snodo.Resource.read/2 runs.
  • {:prompt_get, name} - renders the prompt with params["arguments"], a map of strings to strings.
  • :completion_complete - completes a prompt or resource template argument from the completion/complete params.

Any other operation returns a -32601 error.

Returns {:ok, %Snodo.Result{}} or {:error, %Snodo.Error{}}:

  • An unknown name or URI, an "arguments" value of the wrong shape, or a missing required prompt argument is a -32602 error.
  • A missing required tool argument, tool arguments the schema validator rejects, and a tool that returns {:error, reason} without an Snodo.Error produce {:ok, result} with a Snodo.Result.error/2 result.
  • An Snodo.Error returned by a component, or by the authorization policy in the :invocation phase, is returned unchanged.
  • A component that raises, exits, or returns an invalid value is a -32603 error.

Options:

  • :schema_validator - the Snodo.Schema.Validator module that checks tool arguments and structured output. Defaults to Snodo.Schema.Validator.Passthrough.
  • :authorization - nil or a {module, options} policy, as held in the runtime's authorization field. Defaults to nil, which allows everything.

list_prompts(router)

@spec list_prompts(t()) :: [Snodo.Prompt.Definition.t()]

Returns the definition of every registered prompt, sorted by name.

No authorization policy is applied.

list_resource_templates(router)

@spec list_resource_templates(t()) :: [Snodo.Resource.Definition.t()]

Returns the definition of every resource template, sorted by URI template.

No authorization policy is applied.

list_resources(router)

@spec list_resources(t()) :: [Snodo.Resource.Definition.t()]

Returns the definition of every direct resource, sorted by URI.

No authorization policy is applied.

list_tools(router)

@spec list_tools(t()) :: [Snodo.Tool.Definition.t()]

Returns the definition of every registered tool, sorted by name.

No authorization policy is applied.

new()

@spec new() :: t()

Returns an empty router.

register_prompt(router, prompt)

@spec register_prompt(t(), module()) :: t()

Registers a prompt module under the name in its definition.

Registering the same module again returns the router unchanged. Raises ArgumentError when the module is not a valid Snodo.Prompt or another module already registered the name.

register_resource(router, resource)

@spec register_resource(t(), module()) :: t()

Registers a resource module.

A definition with a :uri registers a direct resource under that URI. A definition with a :uri_template registers a resource template, which answers any URI its Snodo.Resource.matches?/1 accepts. Registering the same module again returns the router unchanged.

Raises ArgumentError when the module is not a valid Snodo.Resource, or when its name, URI, or URI template is already registered by another module. A direct URI that an existing template matches, and a template that matches an existing direct URI, are also refused.

register_tool(router, tool)

@spec register_tool(t(), module()) :: t()

Registers a tool module under the name its Snodo.Tool.name/0 returns.

The module must implement Snodo.Tool with a valid definition. Registering the same module again returns the router unchanged.

Raises ArgumentError when the module cannot be loaded, does not export the Snodo.Tool callbacks, returns an invalid definition, or uses a name that another module already registered.