pub struct SoloMcpServer { /* private fields */ }Expand description
The MCP server. Cheap to clone — every field is Arc-cloneable.
v0.8.0 P2: an MCP session resolves to one tenant. The session’s
tenant_handle is resolved at initialize time (today: from the
CLI invocation via solo mcp-stdio --tenant <id>; future versions
may resolve per-bearer-token via OIDC). Subsequent tools/call
invocations route through the cached handle without re-resolving.
Operators that need multi-tenant MCP spawn one solo mcp-stdio
subprocess per tenant.
Implementations§
Source§impl SoloMcpServer
impl SoloMcpServer
Sourcepub fn new_for_tenant(
registry: Arc<TenantRegistry>,
tenant: Arc<TenantHandle>,
user_aliases: Vec<String>,
) -> Self
pub fn new_for_tenant( registry: Arc<TenantRegistry>, tenant: Arc<TenantHandle>, user_aliases: Vec<String>, ) -> Self
Build a server speaking for tenant (v0.8.0 P2 — one MCP session
↔ one tenant). The registry is held so future capabilities can
reach across tenants if needed; today every handler routes
through self.inner.tenant.
v0.8.1 P2: auto-resolves the audit principal from the
SOLO_MCP_PRINCIPAL_TOKEN env var (see resolve_mcp_principal).
When neither the env var nor a header is set, the principal stays
None — preserving v0.8.0 behavior for single-user setups.
Sourcepub fn new_for_tenant_with_principal(
registry: Arc<TenantRegistry>,
tenant: Arc<TenantHandle>,
user_aliases: Vec<String>,
audit_principal: Option<String>,
) -> Self
pub fn new_for_tenant_with_principal( registry: Arc<TenantRegistry>, tenant: Arc<TenantHandle>, user_aliases: Vec<String>, audit_principal: Option<String>, ) -> Self
v0.8.0 P4: like Self::new_for_tenant, but records an explicit
audit principal subject for every tool dispatch. MCP is
bearer-only at v0.8.0 — the orchestration layer (today: the
daemon’s --bearer-token-file path) decides whether a session
counts as “bearer-authenticated” and passes Some("bearer");
CLI / unauth paths pass None.
v0.8.1 P2: when the caller passes audit_principal = None, the
env-var auto-resolution still runs (in new_for_tenant). Callers
who want to explicitly suppress env-var resolution can call
this method with None after std::env::remove_var(...), or use
the dedicated test constructor that bypasses env reads.
Source§impl SoloMcpServer
impl SoloMcpServer
Sourcepub async fn dispatch_tool(
&self,
name: &str,
args_value: Value,
progress: Option<ProgressReporter>,
) -> Result<CallToolResult, McpError>
pub async fn dispatch_tool( &self, name: &str, args_value: Value, progress: Option<ProgressReporter>, ) -> Result<CallToolResult, McpError>
Direct tool-dispatch path used by both call_tool (the
ServerHandler trait method, behind the rmcp protocol layer) and
in-process tests that don’t want to spin up a full transport pair.
Bypasses RequestContext (which requires a Peer not constructible
outside rmcp internals).
v0.11.0 P3: progress is Some only when the HTTP transport
dispatched the request AND the client opted in via
_meta.progressToken. The three long-running handlers
(memory_ingest_document, memory_search_docs,
memory_remember_batch) consult the reporter; the other
11 handlers ignore it (backward compat with stdio and with
HTTP clients that did not opt in).
Sourcepub fn dispatch_list_tools(&self) -> Vec<Tool>
pub fn dispatch_list_tools(&self) -> Vec<Tool>
List the tools this server exposes. Mirrors ServerHandler::list_tools
without requiring a RequestContext.
Trait Implementations§
Source§impl Clone for SoloMcpServer
impl Clone for SoloMcpServer
Source§fn clone(&self) -> SoloMcpServer
fn clone(&self) -> SoloMcpServer
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl ServerHandler for SoloMcpServer
impl ServerHandler for SoloMcpServer
Source§async fn initialize(
&self,
request: InitializeRequestParams,
context: RequestContext<RoleServer>,
) -> Result<InitializeResult, McpError>
async fn initialize( &self, request: InitializeRequestParams, context: RequestContext<RoleServer>, ) -> Result<InitializeResult, McpError>
v0.9.0 P2: override initialize so we can:
- Cache the client’s
InitializeRequestParamson the peer (delegates to rmcp’s default for this). - If the tenant’s
[llm] mode = "mcp_sampling": a. Refuse to initialize when the peer didn’t advertise thesamplingcapability — surfaces the BLOCKER 2-locked error message so the user sees commented-out alternative TOML blocks. b. Otherwise build aSamplingLlmClient-backed Steward and write it intotenant.steward_slot()so the writer actor’s next consolidate-tick reads a populated slot. - For any other
[llm]mode, return the configured tools surface unchanged (the slot was eagerly populated at registry-open time by the static StewardFactory).
fn get_info(&self) -> ServerInfo
async fn list_tools( &self, _request: Option<PaginatedRequestParam>, _context: RequestContext<RoleServer>, ) -> Result<ListToolsResult, McpError>
async fn call_tool( &self, request: CallToolRequestParam, _context: RequestContext<RoleServer>, ) -> Result<CallToolResult, McpError>
fn enqueue_task( &self, _request: CallToolRequestParams, _context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<CreateTaskResult, ErrorData>> + MaybeSendFuture
fn ping( &self, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn complete( &self, request: CompleteRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<CompleteResult, ErrorData>> + MaybeSendFuture
fn set_level( &self, request: SetLevelRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn get_prompt( &self, request: GetPromptRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<GetPromptResult, ErrorData>> + MaybeSendFuture
fn list_prompts( &self, request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ListPromptsResult, ErrorData>> + MaybeSendFuture
fn list_resources( &self, request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ListResourcesResult, ErrorData>> + MaybeSendFuture
fn list_resource_templates( &self, request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ListResourceTemplatesResult, ErrorData>> + MaybeSendFuture
fn read_resource( &self, request: ReadResourceRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ReadResourceResult, ErrorData>> + MaybeSendFuture
fn subscribe( &self, request: SubscribeRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn unsubscribe( &self, request: UnsubscribeRequestParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<(), ErrorData>> + MaybeSendFuture
fn on_custom_request( &self, request: CustomRequest, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<CustomResult, ErrorData>> + MaybeSendFuture
fn on_cancelled( &self, notification: CancelledNotificationParam, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn on_progress( &self, notification: ProgressNotificationParam, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn on_initialized( &self, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn on_roots_list_changed( &self, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn on_custom_notification( &self, notification: CustomNotification, context: NotificationContext<RoleServer>, ) -> impl Future<Output = ()> + MaybeSendFuture
fn list_tasks( &self, request: Option<PaginatedRequestParams>, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<ListTasksResult, ErrorData>> + MaybeSendFuture
fn get_task_info( &self, request: GetTaskInfoParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<GetTaskResult, ErrorData>> + MaybeSendFuture
fn get_task_result( &self, request: GetTaskResultParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<GetTaskPayloadResult, ErrorData>> + MaybeSendFuture
fn cancel_task( &self, request: CancelTaskParams, context: RequestContext<RoleServer>, ) -> impl Future<Output = Result<CancelTaskResult, ErrorData>> + MaybeSendFuture
Auto Trait Implementations§
impl Freeze for SoloMcpServer
impl !RefUnwindSafe for SoloMcpServer
impl Send for SoloMcpServer
impl Sync for SoloMcpServer
impl Unpin for SoloMcpServer
impl UnsafeUnpin for SoloMcpServer
impl !UnwindSafe for SoloMcpServer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<R, S> DynService<R> for Swhere
R: ServiceRole,
S: Service<R>,
impl<R, S> DynService<R> for Swhere
R: ServiceRole,
S: Service<R>,
fn handle_request( &self, request: <R as ServiceRole>::PeerReq, context: RequestContext<R>, ) -> Pin<Box<dyn Future<Output = Result<<R as ServiceRole>::Resp, ErrorData>> + Send + '_>>
fn handle_notification( &self, notification: <R as ServiceRole>::PeerNot, context: NotificationContext<R>, ) -> Pin<Box<dyn Future<Output = Result<(), ErrorData>> + Send + '_>>
fn get_info(&self) -> <R as ServiceRole>::Info
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more