PluMCP Server
As we saw in Quickstart the main entrypoint of
PluMCP Server is function plumcp.core.api.mcp-server/run-server,
which accepts several options.
Below are few common options (check source for exhaustive list):
:info(required) is MCP server info, may be constructed usingplumcp.core.api.entity-support/make-info:instructions(optional) is a text communicated by the server to the client:transport(optional) is either:stdio(default) or:http:runtime(optional) is derived from other args if unspecified:capabilities(optional) is constructed from options below:primitives(optional) is a map with keys:prompts,:resources,:tools,:callbacks:vars(optional) is a vector of annotated var instances:ns(optional, default: current namespace) is a vector of namespaces
Server capabilities
A PluMCP server makes use of server capabilities to deliver its
features. There are several ways to expose server capabilities.
While :primitives is the low-level way to specify capabilities,
:vars and :ns allow the use of annotated vars to discover
capabilities.
When you specify {:ns [myapp.foo myapp.bar]} it searches through
all annotated vars in those namespaces to discover the primitives.
Similarly, specifying {:vars [#'myapp.foo/baz #'myapp.bar/quux]}
causes only those annotated vars to be scanned as primitives.
Runing an STDIO server
(plumcp.core.api.mcp-server/run-server
{:info server-info
:transport :stdio ; optional
:instructions "..." ; optional
:ns [app.foo app.bar] ; optional
})
Running Streamable HTTP server
(plumcp.core.api.mcp-server/run-server
{:info server-info
:transport :http ; implies Streamable HTTP server
:instructions "..." ; optional
:ns [app.foo app.bar] ; optional
})
Potential Questions
Adapted from: LinkedIn post by Shikha Singh
More reading: Principal AI Engineer Handbook: MCP
How does the agent discover MCP servers and their capabilities?
- It does not "find" them. Servers come from config or an allowlisted registry.
- The initialize handshake (till MCP 2025-11-25 spec) has both sides declare
capabilities. Starting with MCP 2026-07-28 spec, version, client-info and
capabilities are included in
_metaattribute of every request. - The
tools/listresult includes name, description and schema. That is what the LLM sees. - Tool descriptions are prompt input. You should pin and review those.
How do you handle authentication and authorization between the agent and MCP servers?
- The MCP server acts as an OAuth 2.1 resource server.
- When an HTTP request without a valid token lands on the MCP server HTTP 401 is returned with resource metadata, which leads the client to auth-code and PKCE.
- The token is short-lived and audience-bound to that one server.
- The token is not used for passthrough. Downstream APIs get a token exchange.
How do you scope OAuth per capability, especially for sensitive actions?
- Design a tool for single scope, e.g.
payments.readandpayments.transferare distinct scopes - tools using these scopes should serve scoped purpose. - PluMCP checks the OAuth2 scope on every
tools/call. When designing tools you may filter thetools/listby scope. - Missing scope for a call returns HTTP 403
insufficient_scope, followed by step-up and human approval. - Amount, environment and tenant limits may live in gateway policy, with an audit log per user and per agent for traceability.