moonbitstack/moonmcp/server does not have a README file

    Cancellations

    pub struct Cancellations {
    // private fields
    }

    Which requests a client has withdrawn by notifications/cancelled.

    The notification names a request the client already sent, so a transport keeps this beside its read loop: the loop records, the running requests ask.

    Cancellations::add

    fn Cancellations::add(self : Cancellations, id : Json) -> Unit

    Record that the client no longer wants the answer to request id.

    Cancellations::has

    fn Cancellations::has(self : Cancellations, id : Json) -> Bool

    Whether the client has withdrawn request id.

    Cancellations::new

    Nothing withdrawn yet.

    Cancellations::unwatch

    fn Cancellations::unwatch(self : Cancellations, id : Json) -> Unit

    Stop waiting to be told: the request is over.

    Cancellations::watch

    fn Cancellations::watch(self : Cancellations, id : Json, hook : () -> Unit) -> Unit

    Ask to be told when request id is withdrawn. A stream that waits for something other than its own answer, a subscription above all, has no other way to hear about it.

    Channel

    pub(all) struct Channel {
    emit : async (Json) -> Unit
    headers : Map[String, String]
    gone : () -> Bool
    subject : String?
    claims : Map[String, Json]
    }

    What a transport lends one request: the headers that carried it, the way to send a notification before the reply, and whether the caller is still there.

    A transport that can carry nothing beside the reply passes Channel::quiet, which is what Server::handle uses.

    Channel::new

    fn Channel::new(emit~ : async (Json) -> Unit, headers~ : Map[String, String], gone~ : () -> Bool, subject? : String, claims? : Map[String, Json]) -> Channel

    A channel over the transport that carries this request.

    Channel::quiet

    fn Channel::quiet() -> Channel

    A channel with nowhere to send and no caller to lose.

    Scope

    pub(all) enum Scope {
    Public
    Private
    } derive(Eq,
    Debug
    )

    Who may keep a cached list result: any intermediary, or only caches inside the same authorisation context (the cacheScope of a cacheable result).

    Scope::equal

    fn Scope::equal(Scope, Scope) -> Bool

    Scope::not_equal

    fn Scope::not_equal(x : Scope, y : Scope) -> Bool

    Scope::to_cache_scope

    The same scope as the wire names it.

    Scope::to_repr

    Server

    pub struct Server {
    info :
    Implementation

    instructions : String?
    ttl_ms : Int
    scope : Scope
    // private fields
    }

    An MCP server (← FastMCP's FastMCP): the tools, resources, resource templates and prompts it offers, and who it says it is.

    It speaks both eras of the protocol. A request carrying its protocol version in _meta is served statelessly under the 2026-07-28 revision; an initialize request opens the handshake of the revisions before it. The same server is reached over Streamable HTTP with to_asgi, over stdio with run_stdio, or by any transport of your own through handle.

    ttl_ms and scope are the caching hints every list result carries under the 2026-07-28 revision. The presets say "stale at once" and "this caller only", the cautious end of both, since a server that changes what it lists per caller would otherwise leak one caller's list to the next.

    Server::add_prompt

    fn Server::add_prompt(self : Server, prompt :
    Prompt
    ) -> Unit

    Offer prompt. A second prompt under the same name replaces the first.

    Server::add_resource

    fn Server::add_resource(self : Server, resource :
    Resource
    ) -> Unit

    Offer resource at its URI. A second resource at the same URI replaces the first.

    Server::add_template

    Offer template; a URI no fixed resource answers is matched against the templates in the order they were added.

    Server::add_tool

    fn Server::add_tool(self : Server, tool :
    Tool
    ) -> Unit

    Offer tool. Its input schema is compiled here, so a call is checked against it before the tool runs. A schema that does not compile is a mistake in the program, not in a request, so it aborts now rather than failing the first call. A second tool under the same name replaces the first.

    Server::handle

    async fn Server::handle(self : Server, message : Json) -> Json?

    Answer one JSON-RPC message, the way every transport does (← the low-level server's message loop). None is the answer to a notification. A message that is not JSON-RPC at all is answered with the error JSON-RPC prescribes, under a null id.

    This is the form for a caller with no channel of its own, so a handler's progress reports and log messages are dropped. A transport that can carry them calls handle_with.

    Server::handle_with

    async fn Server::handle_with(self : Server, message : Json, channel~ : Channel) -> Json?

    Answer one message over channel, which carries the request's headers and whatever the handlers send beside the reply.

    Server::log_to

    fn Server::log_to(self : Server, logger~ :
    Logger
    ) -> Unit

    Write the server's own log through logger (← a structured logger passed in, never reached for globally): a request served, a request refused, a subscription opened. Context::log writes here too, beside the notification it sends, so a client that went away does not take the record with it.

    Without one the server keeps no log of its own; the notifications/message its handlers ask for still go to the client.

    Server::new

    fn Server::new(name : String, version? : String, title? : String, instructions? : String, ttl_ms? : Int, scope? : Scope) -> Server

    Server::notify

    fn Server::notify(self : Server, message : Json) -> Unit

    Hand message to every subscription whose filter asked for it. A subscription that has stopped reading its queue is dropped rather than allowed to hold the change.

    Server::notify_prompts_changed

    fn Server::notify_prompts_changed(self : Server) -> Unit

    Tell every subscription that the prompts changed.

    Server::notify_resource_updated

    fn Server::notify_resource_updated(self : Server, uri : String) -> Unit

    Tell the subscriptions that asked for uri that it was rewritten.

    Server::notify_resources_changed

    fn Server::notify_resources_changed(self : Server) -> Unit

    Tell every subscription that the resources changed.

    Server::notify_tools_changed

    fn Server::notify_tools_changed(self : Server) -> Unit

    Tell every subscription that the tools changed. Registering a tool does this by itself; a server whose tools come and go for reasons of its own calls it when it knows.

    Server::prompt

    fn Server::prompt(self : Server, name : String, render : async (Map[String, Json]) -> String, title? : String, description? : String, arguments? : Array[
    PromptArgument
    ]) -> Unit

    Offer a prompt rendered as one user message (← @mcp.prompt).

    Server::prompt_context

    fn Server::prompt_context(self : Server, name : String, render : async (Map[String, Json],
    Context
    ) ->
    RenderedPrompt
    , title? : String, description? : String, arguments? : Array[
    PromptArgument
    ]) -> Unit

    Offer a prompt whose renderer sees the request it serves.

    Server::resource

    fn Server::resource(self : Server, uri : String, read : async () -> String, name? : String, title? : String, description? : String, mime_type? : String) -> Unit

    Offer a resource read as text (← @mcp.resource(uri)).

    Server::resource_context

    fn Server::resource_context(self : Server, uri : String, read : async (
    Context
    ) ->
    RawResourceValue
    , name? : String, title? : String, description? : String, mime_type? : String) -> Unit

    Offer a resource whose reader sees the request it serves. A read that needs something from the client answers with ResourceResult::input_required instead of contents.

    Server::run_stdio

    async fn Server::run_stdio(self : Server) -> Unit

    Serve over the process's standard input and output (← FastMCP's run(transport="stdio")): one message per line each way, until standard input closes. Anything else the program prints belongs on standard error, since standard output carries nothing but messages.

    Server::serve_lines

    async fn Server::serve_lines(self : Server, read : async () -> String?, write : async (String) -> Unit) -> Unit

    Serve newline-delimited JSON-RPC: read a line with read until it gives None, answer it, and write the reply as one line (← the stdio transport, over any pair of streams). A line that is not JSON is answered with a parse error; a blank one is skipped.

    Requests are worked on as they arrive, each in a task of its own, so a slow tool does not hold up the next call. Replies still leave in the order their requests came in, which is what a client that counts lines expects; a subscription's notifications are the exception, since they are not replies to anything.

    notifications/cancelled withdraws the request it names, which the running task sees through its context.

    Server::serve_subscription

    async fn Server::serve_subscription(self : Server, id : Json, params : Map[String, Json], channel : Channel, cancellations? : Cancellations, queue? :
    Queue
    [Json]) -> Unit

    Serve one subscriptions/listen request until the transport lets go: the acknowledgement first, then every notification the filter asked for, each tagged with the id of the request that opened the stream.

    The reply to the request itself is sent by the caller when this returns, and only when it returns of its own accord: a stream cut by the transport has no reply, as the specification has it.

    Server::template

    fn Server::template(self : Server, uri_template : String, read : async (Map[String, Json]) -> String, name? : String, title? : String, description? : String, mime_type? : String) -> Unit

    Offer the resources an RFC 6570 template names, read as text with the parameters the URI matched (← @mcp.resource("users://{id}")). A template that does not parse aborts at registration.

    Server::template_context

    fn Server::template_context(self : Server, uri_template : String, read : async (Map[String, Json],
    Context
    ) ->
    RawResourceValue
    , name? : String, title? : String, description? : String, mime_type? : String) -> Unit

    Offer the resources an RFC 6570 template names, read in the request that matched them.

    Server::to_asgi

    fn Server::to_asgi(self : Server, path? : String, origins? : Array[String], docs? : String?, theme? :
    Theme
    , auth? :
    Bearer
    ?) -> (async (
    Scope
    , async () ->
    Event
    , async (
    Event
    ) -> Unit) -> Unit)

    The server as an ASGI application serving the MCP endpoint at path (← FastMCP's http_app). Run it with mooncat, or mount it beside a moonapi app.

    Every message is its own POST, answered with one JSON object, or 202 for a notification. Sessions, the GET stream and DELETE belong to the revisions before 2026-07-28 and are optional there; this server keeps no session, so GET and DELETE answer 405.

    A 2026-07-28 request that offers a progress token, or that opens a subscription, is answered with text/event-stream when the client accepts it: the notifications the handler sends arrive on that stream, and the reply ends it.

    A request whose Origin header names another site is refused with 403, as the transport requires against DNS rebinding. An origin passes when its host is the request's own Host, a loopback address, or one listed in origins.

    docs names the path the documentation page is served at, beside the endpoint: a browser opened on it lists what the server offers and calls it, in both eras of the protocol. It is on at /docs unless told otherwise, as an API framework's interactive docs are; docs=None leaves it off, and a path equal to the endpoint's is ignored. theme picks its look, the moonmcp website's by default. The page carries no credentials of its own.

    Server::tool

    fn Server::tool(self : Server, name : String, run : async (Map[String, Json]) -> Json, input_schema? : Json, title? : String, description? : String, output_schema? : Json, annotations? :
    ToolAnnotations
    ) -> Unit

    Offer a tool whose handler returns any JSON value (← @mcp.tool). An object becomes structured content as well as text; anything else becomes text. An error the handler raises becomes a result marked isError, which the model reads and can correct itself from. A name the protocol does not allow aborts at registration.

    Server::tool_context

    fn Server::tool_context(self : Server, name : String, run : async (Map[String, Json],
    Context
    ) ->
    ToolResult
    , input_schema? : Json, title? : String, description? : String, output_schema? : Json, annotations? :
    ToolAnnotations
    ) -> Unit

    Offer a tool that also sees the request it serves (← FastMCP's Context parameter): its identity in _meta, the headers that carried it, the progress token it offered, and whatever the client answered on a retry.

    The handler answers with a ToolResult. An ordinary one carries content; ToolResult::input_required carries an ask instead, which the client satisfies and then sends the same call again with inputResponses and requestState, or with an answer if it cannot.

    decode

    The argument name of a call, read as T; the code #mcp.tool generates calls this for each required parameter. A string read where something else is wanted is read again as JSON, which is how the {id} of a resource template, always text, reaches an Int parameter.

    decode_option

    fn[T :
    FromJson
    ] decode_option(args : Map[String, Json], name : String) -> T? raise
    JsonDecodeError

    The argument name of a call when it may be left out: None when it is missing or null, else the value read as decode reads it. The code #mcp.tool generates calls this for optional parameters.

    list_changed_notification

    fn list_changed_notification(operation : String) -> Json

    The notification that a server's tools, prompts or resources changed.

    method_of

    fn method_of(message : Json) -> String?

    The method a message names, if it is a JSON-RPC one at all.

    params_of

    fn params_of(message : Json) -> Map[String, Json]

    The parameters a message carries, empty when it carries none.

    request_id_of

    fn request_id_of(message : Json) -> Json?

    The id a request carries; None on a notification.

    resource_updated_notification

    fn resource_updated_notification(uri : String) -> Json

    The notification that one resource was rewritten.

    subscription_closed_result

    fn subscription_closed_result(id : Json) -> Json

    The reply that closes a subscription the server ended on purpose, carrying the id of the stream so a client can pair it with the request.

    Powered by MoonBit

    Site sourceReport issueModulesSkillsBuild queueStatistics

    © 2026 mooncakes.io