API Reference
ModelContextProtocol.FEATURE_VERSIONSModelContextProtocol.GITHUB_API_URLModelContextProtocol.GitHubAuthorizationServerModelContextProtocol.LATEST_MODERN_PROTOCOL_VERSIONModelContextProtocol.LATEST_PROTOCOL_VERSIONModelContextProtocol.MCP_LOG_LEVELSModelContextProtocol.MODERN_CACHEABLE_METHODSModelContextProtocol.MODERN_METHODSModelContextProtocol.MODERN_PROTOCOL_VERSIONSModelContextProtocol.SUPPORTED_PROTOCOL_VERSIONSModelContextProtocol.WELL_KNOWN_PATHModelContextProtocol.AudioContentModelContextProtocol.AuthMiddlewareModelContextProtocol.AuthProviderModelContextProtocol.AuthResultModelContextProtocol.AuthenticatedUserModelContextProtocol.BlobResourceContentsModelContextProtocol.CallToolParamsModelContextProtocol.CallToolResultModelContextProtocol.CancelTaskParamsModelContextProtocol.CapabilityModelContextProtocol.CapabilityResponseModelContextProtocol.ClientCapabilitiesModelContextProtocol.CompleteParamsModelContextProtocol.CompletionArgumentModelContextProtocol.CompletionCapabilityModelContextProtocol.CompletionReferenceModelContextProtocol.ContentModelContextProtocol.EmbeddedResourceModelContextProtocol.ErrorInfoModelContextProtocol.GetPromptParamsModelContextProtocol.GetPromptResultModelContextProtocol.GetTaskParamsModelContextProtocol.GitHubOAuthValidatorModelContextProtocol.GitHubOAuthValidatorWithOrgModelContextProtocol.HandlerResultModelContextProtocol.HttpTransportModelContextProtocol.ImageContentModelContextProtocol.ImplementationModelContextProtocol.InitializeParamsModelContextProtocol.InitializeResultModelContextProtocol.InputRequestModelContextProtocol.InputRequiredModelContextProtocol.IntrospectionValidatorModelContextProtocol.JSONRPCErrorModelContextProtocol.JSONRPCNotificationModelContextProtocol.JSONRPCRequestModelContextProtocol.JSONRPCResponseModelContextProtocol.JWKSValidatorModelContextProtocol.JWTValidatorModelContextProtocol.ListPromptsParamsModelContextProtocol.ListPromptsResultModelContextProtocol.ListResourceTemplatesParamsModelContextProtocol.ListResourcesParamsModelContextProtocol.ListResourcesResultModelContextProtocol.ListTasksParamsModelContextProtocol.ListToolsParamsModelContextProtocol.ListToolsResultModelContextProtocol.LoggingCapabilityModelContextProtocol.MCPIconModelContextProtocol.MCPLoggerModelContextProtocol.MCPLoggerModelContextProtocol.MCPMessageModelContextProtocol.MCPPromptModelContextProtocol.MCPResourceModelContextProtocol.MCPToolModelContextProtocol.ModernRequestLoggerModelContextProtocol.NotificationModelContextProtocol.OAuthConfigModelContextProtocol.PendingTaskInputModelContextProtocol.ProgressModelContextProtocol.ProgressParamsModelContextProtocol.ProgressTokenModelContextProtocol.PromptArgumentModelContextProtocol.PromptCapabilityModelContextProtocol.PromptMessageModelContextProtocol.ProtectedResourceMetadataModelContextProtocol.QueuedHttpRequestModelContextProtocol.ReadResourceParamsModelContextProtocol.ReadResourceResultModelContextProtocol.RequestModelContextProtocol.RequestAuthContextModelContextProtocol.RequestContextModelContextProtocol.RequestHandlerModelContextProtocol.RequestIdModelContextProtocol.RequestMetaModelContextProtocol.RequestParamsModelContextProtocol.ResourceModelContextProtocol.ResourceCapabilityModelContextProtocol.ResourceContentsModelContextProtocol.ResourceLinkModelContextProtocol.ResourceTemplateModelContextProtocol.ResponseModelContextProtocol.ResponseResultModelContextProtocol.RoleModelContextProtocol.ServerModelContextProtocol.ServerConfigModelContextProtocol.ServerErrorModelContextProtocol.ServerStateModelContextProtocol.SetLevelParamsModelContextProtocol.SimpleTokenValidatorModelContextProtocol.StdioTransportModelContextProtocol.SubscribeParamsModelContextProtocol.SubscriptionModelContextProtocol.SubscriptionFilterModelContextProtocol.SubscriptionRecordModelContextProtocol.SubscriptionRegistryModelContextProtocol.SubscriptionsListenParamsModelContextProtocol.TaskCancelledExceptionModelContextProtocol.TaskCapabilityModelContextProtocol.TaskDetachStateModelContextProtocol.TaskRecordModelContextProtocol.TaskResultParamsModelContextProtocol.TaskStoreModelContextProtocol.TextContentModelContextProtocol.TextResourceContentsModelContextProtocol.TokenValidatorModelContextProtocol.ToolModelContextProtocol.ToolCapabilityModelContextProtocol.ToolParameterModelContextProtocol.TransportModelContextProtocol.TransportErrorModelContextProtocol.UnsubscribeParamsModelContextProtocol.UpdateTaskParamsBase.convertLogging.handle_messageModelContextProtocol._fire_status_changeModelContextProtocol._json_integer_valueModelContextProtocol.accepts_sseModelContextProtocol.add_token!ModelContextProtocol.auth_error_responseModelContextProtocol.authenticate_requestModelContextProtocol.auto_register!ModelContextProtocol.broadcast_subscription_notificationModelContextProtocol.broadcast_to_sseModelContextProtocol.call_tool_result_wireModelContextProtocol.cancel_subscription!ModelContextProtocol.cancel_task!ModelContextProtocol.canonical_json_digestModelContextProtocol.canonicalize_jsonModelContextProtocol.capabilities_to_protocolModelContextProtocol.capability_satisfiedModelContextProtocol.capture_response_routeModelContextProtocol.capture_response_routeModelContextProtocol.check_allowlistModelContextProtocol.check_github_org_membershipModelContextProtocol.clear_cache!ModelContextProtocol.closeModelContextProtocol.closeModelContextProtocol.closeModelContextProtocol.close_scope!ModelContextProtocol.close_subscriptions!ModelContextProtocol.collect_param_headersModelContextProtocol.completion_valuesModelContextProtocol.connectModelContextProtocol.content2dictModelContextProtocol.convert_to_content_typeModelContextProtocol.create_auth_middlewareModelContextProtocol.create_github_authModelContextProtocol.create_github_resource_metadataModelContextProtocol.create_init_responseModelContextProtocol.create_protected_resource_metadataModelContextProtocol.create_simple_authModelContextProtocol.create_task!ModelContextProtocol.decode_jwt_headerModelContextProtocol.decode_jwt_payloadModelContextProtocol.decode_mcp_header_valueModelContextProtocol.default_capabilitiesModelContextProtocol.deliver_log_notificationModelContextProtocol.deliver_log_notificationModelContextProtocol.deliver_notificationModelContextProtocol.deliver_notificationModelContextProtocol.deliver_responseModelContextProtocol.deliver_responseModelContextProtocol.disable_authModelContextProtocol.dispatch_modernModelContextProtocol.drain_pending_inputs!ModelContextProtocol.elicit_requestModelContextProtocol.end_responseModelContextProtocol.ensure_task_notifications!ModelContextProtocol.execute_tool_callModelContextProtocol.expire_parked_input!ModelContextProtocol.ext_task_authorizedModelContextProtocol.ext_task_principalModelContextProtocol.ext_task_wireModelContextProtocol.extract_bearer_tokenModelContextProtocol.fetch_github_userModelContextProtocol.fetch_jwks_http_bodyModelContextProtocol.fetch_jwks_keysModelContextProtocol.filter_to_wireModelContextProtocol.filter_wantsModelContextProtocol.finish_task!ModelContextProtocol.flushModelContextProtocol.flushModelContextProtocol.format_log_notificationModelContextProtocol.format_sse_eventModelContextProtocol.generate_session_idModelContextProtocol.get_params_typeModelContextProtocol.get_result_typeModelContextProtocol.get_taskModelContextProtocol.handle_call_toolModelContextProtocol.handle_cancel_taskModelContextProtocol.handle_completeModelContextProtocol.handle_discoverModelContextProtocol.handle_ext_cancel_taskModelContextProtocol.handle_ext_get_taskModelContextProtocol.handle_ext_update_taskModelContextProtocol.handle_get_taskModelContextProtocol.handle_initializeModelContextProtocol.handle_list_promptsModelContextProtocol.handle_list_resource_templatesModelContextProtocol.handle_list_resourcesModelContextProtocol.handle_list_tasksModelContextProtocol.handle_list_toolsModelContextProtocol.handle_modern_requestModelContextProtocol.handle_notificationModelContextProtocol.handle_pingModelContextProtocol.handle_read_resourceModelContextProtocol.handle_requestModelContextProtocol.handle_requestModelContextProtocol.handle_set_levelModelContextProtocol.handle_sse_streamModelContextProtocol.handle_subscribe_resourceModelContextProtocol.handle_subscriptions_listenModelContextProtocol.handle_task_resultModelContextProtocol.handle_unsubscribe_resourceModelContextProtocol.handle_well_known_requestModelContextProtocol.icon_to_dictModelContextProtocol.init_loggingModelContextProtocol.input_required_envelopeModelContextProtocol.input_responsesModelContextProtocol.input_stateModelContextProtocol.install_task_notifications!ModelContextProtocol.is_auth_enabledModelContextProtocol.is_connectedModelContextProtocol.is_connectedModelContextProtocol.is_connectedModelContextProtocol.is_loopback_hostModelContextProtocol.is_supported_versionModelContextProtocol.is_valid_session_idModelContextProtocol.iso8601_utcModelContextProtocol.issue_request_stateModelContextProtocol.legacy_session_notificationModelContextProtocol.list_changed_declaredModelContextProtocol.list_tasksModelContextProtocol.lookup_jwks_key!ModelContextProtocol.match_uri_templateModelContextProtocol.mcp_level_severityModelContextProtocol.mcp_level_to_juliaModelContextProtocol.mcp_serverModelContextProtocol.mcp_standard_headerModelContextProtocol.merge_capabilitiesModelContextProtocol.metadata_to_jsonModelContextProtocol.modern_cache_scopeModelContextProtocol.modern_error_http_statusModelContextProtocol.modern_header_violationModelContextProtocol.modern_input_required_responseModelContextProtocol.modern_invalid_paramsModelContextProtocol.modern_method_availableModelContextProtocol.modern_result_envelopeModelContextProtocol.modernize_error_codeModelContextProtocol.mrtr_principalModelContextProtocol.negotiate_versionModelContextProtocol.normalize_pathModelContextProtocol.normalize_read_contentsModelContextProtocol.notification_routeModelContextProtocol.notification_routeModelContextProtocol.notify_list_changedModelContextProtocol.notify_resource_updatedModelContextProtocol.notify_task_statusModelContextProtocol.param_header_violationModelContextProtocol.parse_error_responseModelContextProtocol.parse_host_headerModelContextProtocol.parse_messageModelContextProtocol.parse_notificationModelContextProtocol.parse_requestModelContextProtocol.parse_subscription_filterModelContextProtocol.parse_success_responseModelContextProtocol.pending_auth_contextModelContextProtocol.pending_auth_contextModelContextProtocol.pending_param_headersModelContextProtocol.pending_param_headersModelContextProtocol.principal_identityModelContextProtocol.process_messageModelContextProtocol.read_messageModelContextProtocol.read_messageModelContextProtocol.read_messageModelContextProtocol.rebinding_violationModelContextProtocol.register!ModelContextProtocol.request_protocol_versionModelContextProtocol.roots_requestModelContextProtocol.route_aliveModelContextProtocol.route_aliveModelContextProtocol.run_server_loopModelContextProtocol.safe_error_messageModelContextProtocol.sampling_requestModelContextProtocol.scan_mcp_componentsModelContextProtocol.send_notificationModelContextProtocol.send_notificationModelContextProtocol.send_progressModelContextProtocol.serialize_messageModelContextProtocol.serialize_resource_contentsModelContextProtocol.serve_modernModelContextProtocol.set_negotiated_version!ModelContextProtocol.set_negotiated_version!ModelContextProtocol.spawn_detachable_tool_call!ModelContextProtocol.spawn_task_execution!ModelContextProtocol.split_outside_quotesModelContextProtocol.start!ModelContextProtocol.stop!ModelContextProtocol.subscribe!ModelContextProtocol.subscription_notificationModelContextProtocol.supportsModelContextProtocol.sweep_expired!ModelContextProtocol.task_await_inputModelContextProtocol.task_cancelledModelContextProtocol.task_detachModelContextProtocol.task_is_expiredModelContextProtocol.task_is_terminalModelContextProtocol.task_principalModelContextProtocol.task_terminal_responseModelContextProtocol.task_wireModelContextProtocol.tasks_cancel_offeredModelContextProtocol.tasks_extension_declaredModelContextProtocol.tasks_extension_required_errorModelContextProtocol.tasks_list_offeredModelContextProtocol.tasks_supportedModelContextProtocol.to_protocol_formatModelContextProtocol.undeclared_capability_requirementsModelContextProtocol.unsubscribe!ModelContextProtocol.validate_jwt_claimsModelContextProtocol.validate_tokenModelContextProtocol.validate_tool_headersModelContextProtocol.verify_request_stateModelContextProtocol.with_related_task_metaModelContextProtocol.write_messageModelContextProtocol.write_messageModelContextProtocol.write_messageStructTypes.namesStructTypes.omitemptiesStructTypes.omitemptiesStructTypes.omitempties
Primary Interface
ModelContextProtocol.mcp_server — Function
mcp_server(; name::String, version::String="1.0.0",
tools::Union{Vector{MCPTool},MCPTool,Nothing}=nothing,
resources::Union{Vector{MCPResource},MCPResource,Nothing}=nothing,
prompts::Union{Vector{MCPPrompt},MCPPrompt,Nothing}=nothing,
description::String="",
instructions::String="",
capabilities::Vector{Capability}=default_capabilities(),
auto_register_dir::Union{String,Nothing}=nothing,
title::Union{String,Nothing}=nothing,
icons::Union{Vector{MCPIcon},Nothing}=nothing) -> ServerPrimary entry point for creating and configuring a Model Context Protocol (MCP) server.
Arguments
name::String: Unique identifier for the server instanceversion::String: Your server implementation version (defaults to "1.0.0") - YOUR server's version, not the MCP protocol versiontools: Tools to expose to the modelresources: Resources available to the modelresource_templates: Parameterized resource families (RFC 6570{var}URI templates with a provider; advertised viaresources/templates/list)prompts: Predefined prompts for the modeldescription::String: Optional server descriptioninstructions::String: Optional natural-language guidance for LLM clients on using this server (returned by legacyinitializeand modernserver/discover)capabilities::Vector{Capability}: Server capability configurationauto_register_dir: Directory to auto-register components fromtitle::Union{String,Nothing}: Optional human-friendly display name for the servericons::Union{Vector{MCPIcon},Nothing}: Optional icons for the servermrtr_state_key::Union{Vector{UInt8},Nothing}: Optional MRTRrequestStatesigning key (≥32 bytes) shared across replicas so retries survive re-routing; defaults to a random per-server key (single-instance safe). Tokens also carry a format version: replicas on different package versions that change it reject each other's tokens ("unsupported version"), so a rolling upgrade across such a change should drain in-flight MRTR exchanges (bounded by the 600s state TTL)
Returns
Server: A configured server instance ready to handle MCP client connections
Example
server = mcp_server(
name = "my-server",
version = "1.0.0", # Your server version
title = "My MCP Server",
description = "Demo server with time tool",
tools = MCPTool(
name = "get_time",
description = "Get current time",
parameters = [],
handler = args -> Dates.format(now(), "HH:MM:SS")
)
)
start!(server)Server Operations
ModelContextProtocol.start! — Function
start!(server::Server; transport::Union{Transport,Nothing}=nothing) -> NothingStart the MCP server, setting up logging and entering the main server loop.
Arguments
server::Server: The server instance to starttransport::Union{Transport,Nothing}: Optional transport to use. If not provided, uses StdioTransport
Returns
Nothing: The function returns after the server stops
Throws
ServerError: If the server is already running
ModelContextProtocol.stop! — Function
stop!(server::Server) -> NothingStop a running MCP server: the server loop observes active == false on its next iteration and exits with the transport still open, so shutdown can deliver each subscriptions/listen stream's graceful closing result before the transport closes.
On HTTP this takes effect within the loop's bounded read wait. On stdio the loop blocks in readline, so stop! only takes effect when the next message — or EOF — arrives; the normal stdio lifecycle ends via stdin EOF, which runs the same graceful-closure path.
Arguments
server::Server: The server instance to stop
Returns
Nothing: The function returns after setting the server to inactive
Throws
ServerError: If the server is not currently running
ModelContextProtocol.register! — Function
register!(server::Server, component::Union{Tool,Resource,MCPPrompt}) -> ServerRegister a tool, resource, or prompt with the MCP server.
Arguments
server::Server: The server to register the component withcomponent: The component to register (can be a tool, resource, or prompt)
Returns
Server: The server instance for method chaining
Component Types
Tools
ModelContextProtocol.MCPTool — Type
MCPTool(; name::String, description::String, parameters::Vector{ToolParameter}=ToolParameter[],
input_schema::Union{Nothing,AbstractDict}=nothing, handler::Function,
return_type::Type=Vector{Content}) <: ToolImplement a tool that can be invoked by clients in the MCP protocol.
Fields
name::String: Unique identifier for the tooldescription::String: Human-readable description of the tool's purposeparameters::Vector{ToolParameter}: Simple parameters (ignored if input_schema is provided)input_schema::Union{Nothing,AbstractDict}: Raw JSON Schema for complex parameter typeshandler::Function: Function that implements the tool's functionalityreturn_type::Type: Expected return type of the handler (defaults to Vector{Content})annotations::Union{Nothing,Dict{String,Any}}: Optional tool annotations (behavioral hints for clients), e.g.Dict("readOnlyHint" => true, "destructiveHint" => false, "idempotentHint" => true, "openWorldHint" => false). Emitted verbatim intools/list`.output_schema::Union{Nothing,AbstractDict}: Optional JSON Schema for the tool's structured result, emitted asoutputSchemaintools/list. Pair it with aCallToolResult(structured_content=…)so clients can validate the structured output._meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions, emitted verbatim intools/listwhen settask_support::Symbol: Task-augmented execution support (MCP 2025-11-25, experimental)::forbidden(default — calls run synchronously),:optional(client may run the call as a task), or:required(client must run the call as a task). Emitted asexecution.taskSupportintools/listfor clients that negotiated 2025-11-25.required_scopes::Vector{String}: OAuth scopes the caller must hold to invoke this tool. Enforced attools/calldispatch when the request carries an authenticated principal (HTTP auth active): every listed scope must be present onctx.authenticated_user.scopesor the call is refused with an insufficient-scope error. Empty (default) means no per-tool requirement. When auth is not configured (no authenticated user) the check is skipped — the server performs no authorization. Not emitted intools/list(it is server-side policy, not part of the tool's schema).
Parameter Definition
Tools can define parameters in two ways:
Simple parameters using
parameters::Vector{ToolParameter}: Good for flat schemas with basic types (string, number, boolean).Complex schemas using
input_schema::AbstractDict: Supports arrays, enums, nested objects, and any valid JSON Schema. When provided,input_schematakes precedence overparameters.
Handler Return Types
The tool handler can return various types which are automatically converted:
- An instance of the specified Content type (TextContent, ImageContent, etc.)
- A Vector{<:Content} for multiple content items (can mix TextContent, ImageContent, etc.)
- A Dict (automatically converted to JSON and wrapped in TextContent)
- A String (automatically wrapped in TextContent)
- A Tuple{Vector{UInt8}, String} (automatically wrapped in ImageContent)
- A CallToolResult object for full control over the response (including error handling)
When returntype is Vector{Content} (default), single Content items are automatically wrapped in a vector. Note: When returning CallToolResult directly, the returntype field is ignored.
ModelContextProtocol.ToolParameter — Type
ToolParameter(; name::String, description::String, type::String, required::Bool=false,
default::Any=nothing, header::Union{String,Nothing}=nothing)Define a parameter for an MCP tool.
Fields
name::String: The parameter name (used as the key in the params dictionary)description::String: Human-readable description of the parametertype::String: Type of the parameter as specified in the MCP schema (e.g., "string", "number", "boolean")required::Bool: Whether the parameter is required for tool invocationdefault::Any: Default value for the parameter if not provided (nothing means no default)header::Union{String,Nothing}: Optional SEP-2243 header-mirroring suffix, emitted asx-mcp-headerin the generated schema: modern HTTP clients mirror the argument as anMcp-Param-<header>request header (for routing), which the server validates against the body
ModelContextProtocol.MCPIcon — Type
MCPIcon(; src::String, mimeType=nothing, sizes=nothing, theme=nothing)Icon metadata for tools, resources, prompts, and server info (MCP 2025-11-25).
Fields
src::String: URI pointing to the icon (http/https URL or data: URI)mimeType::Union{String,Nothing}: MIME type override (e.g., "image/png", "image/svg+xml")sizes::Union{Vector{String},Nothing}: Size hints (e.g., ["48x48", "any"])theme::Union{String,Nothing}: Which background the icon is designed for ("light" or "dark")
Resources
ModelContextProtocol.MCPResource — Type
MCPResource <: ResourceImplement a resource that clients can access in the MCP protocol. Resources represent data that can be read by models and tools.
Fields
uri::URI: Unique identifier for the resourcename::String: Human-readable name for the resourcedescription::String: Detailed description of the resourcemime_type::String: MIME type of the resource datadata_provider::Function: Zero-argument function returning the resource data forresources/read. Return aTextResourceContents/BlobResourceContents(or a vector of them) for full control —BlobResourceContentsis how binary resources are served (base64blobon the wire). AStringis used as the text verbatim; any other value is JSON-encoded into a text contents entry with the resource'smime_type.annotations::AbstractDict{String,Any}: Additional metadata for the resource
ModelContextProtocol.ResourceTemplate — Type
ResourceTemplate(; name::String, uri_template::String,
mime_type::Union{String,Nothing}=nothing, description::String="",
title::Union{String,Nothing}=nothing,
icons::Union{Vector{MCPIcon},Nothing}=nothing,
data_provider::Union{Function,Nothing}=nothing,
_meta::Union{Nothing,Dict{String,Any}}=nothing)Define a parameterized family of resources: an RFC 6570 URI template (level-1 {var} placeholders, advertised via resources/templates/list) plus a provider that serves any resources/read whose URI matches the template.
Fields
name::String: Name of the resource templateuri_template::String: URI template with{var}placeholders; each placeholder matches one path segment (no/)mime_type::Union{String,Nothing}: MIME type shared by all matching resourcesdescription::String: Human-readable description of the templatetitle::Union{String,Nothing}: Optional human-friendly display nameicons::Union{Vector{MCPIcon},Nothing}: Optional icons for UI displaydata_provider::Union{Function,Nothing}: Called for a matchingresources/readasprovider(uri::String)— or opt intoprovider(uri::String, vars::Dict{String,String})to receive the extracted template variables. Return values follow the same contract asMCPResourceproviders (ResourceContents/vector,Stringverbatim, JSON fallback). Templates without a provider are advertised but not readable._meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions, emitted verbatim inresources/templates/listwhen setcompletions::Union{Nothing,Dict{String,Any}}: Optionalcompletion/completesources per template variable name: aVector{String}(served filtered by prefix against the partial value) or a functionvalue -> values/(value, context_args) -> valuesreturning the suggestions
Prompts
ModelContextProtocol.MCPPrompt — Type
MCPPrompt(; name::String, description::String="",
arguments::Vector{PromptArgument}=PromptArgument[],
messages::Vector{PromptMessage}=PromptMessage[],
title::Union{String,Nothing}=nothing,
icons::Union{Vector{MCPIcon},Nothing}=nothing,
completions::Union{Nothing,Dict{String,Any}}=nothing)Implement a prompt or prompt template as defined in the MCP schema. Prompts can include variables that are replaced with arguments when retrieved.
Fields
name::String: Unique identifier for the promptdescription::String: Human-readable description of the prompt's purposearguments::Vector{PromptArgument}: Arguments that this prompt acceptsmessages::Vector{PromptMessage}: The sequence of messages in the prompttitle::Union{String,Nothing}: Optional human-friendly display nameicons::Union{Vector{MCPIcon},Nothing}: Optional icons for UI display_meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions, emitted verbatim inprompts/listwhen setcompletions::Union{Nothing,Dict{String,Any}}: Optionalcompletion/completesources per argument name: aVector{String}(served filtered by prefix against the partial value) or a functionvalue -> values/(value, context_args) -> valuesreturning the suggestions
ModelContextProtocol.PromptArgument — Type
PromptArgument(; name::String, description::String="", required::Bool=false,
title::Union{String,Nothing}=nothing)Define an argument that a prompt template can accept.
Fields
name::String: The argument name (used in template placeholders)description::String: Human-readable description of the argumentrequired::Bool: Whether the argument is required when using the prompttitle::Union{String,Nothing}: Optional human-friendly display name
ModelContextProtocol.PromptMessage — Type
PromptMessage(; content::Union{TextContent, ImageContent, AudioContent, ResourceLink, EmbeddedResource}, role::Role=user)Represent a single message in a prompt template.
Fields
content::Union{TextContent, ImageContent, AudioContent, ResourceLink, EmbeddedResource}: The content of the messagerole::Role: Whether this message is from the user or assistant (defaults to user)
Content Types
Abstract Types
ModelContextProtocol.Content — Type
ContentAbstract base type for all content formats in the MCP protocol. Content can be exchanged between clients and servers in various formats.
ModelContextProtocol.ResourceContents — Type
ResourceContentsAbstract base type for resource content formats in the MCP protocol. Resources can contain different types of content based on their MIME type.
Concrete Content Types
ModelContextProtocol.TextContent — Type
TextContent(; type::String="text", text::String,
annotations::Union{Nothing,Dict{String,Any}}=nothing,
_meta::Union{Nothing,Dict{String,Any}}=nothing) <: ContentText-based content for messages and tool responses.
Fields
type::String: Content type identifier (always "text")text::String: The actual text contentannotations::Union{Nothing,Dict{String,Any}}: Optional annotations for the client_meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions
ModelContextProtocol.ImageContent — Type
ImageContent(; type::String="image", data::Vector{UInt8}, mime_type::String,
annotations::Union{Nothing,Dict{String,Any}}=nothing,
_meta::Union{Nothing,Dict{String,Any}}=nothing) <: ContentImage content for messages and tool responses.
Fields
type::String: Content type identifier (always "image")data::Vector{UInt8}: Raw image data (automatically base64-encoded when serialized)mime_type::String: MIME type of the image (e.g., "image/png")annotations::Union{Nothing,Dict{String,Any}}: Optional annotations for the client_meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions
ModelContextProtocol.AudioContent — Type
AudioContent(; type::String="audio", data::Vector{UInt8}, mime_type::String,
annotations::Union{Nothing,Dict{String,Any}}=nothing,
_meta::Union{Nothing,Dict{String,Any}}=nothing) <: ContentAudio content for messages and tool responses (protocol 2025-03-26+).
Fields
type::String: Content type identifier (always "audio")data::Vector{UInt8}: Raw audio data (automatically base64-encoded when serialized)mime_type::String: MIME type of the audio (e.g., "audio/wav"), serialized asmimeTypeannotations::Union{Nothing,Dict{String,Any}}: Optional annotations for the client_meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions
ModelContextProtocol.EmbeddedResource — Type
EmbeddedResource(; type::String="resource", resource::Dict{String,Any},
annotations::Union{Nothing,Dict{String,Any}}=nothing,
_meta::Union{Nothing,Dict{String,Any}}=nothing) <: ContentEmbedded resource content for inline resource data.
Fields
type::String: Content type identifier (always "resource")resource::Dict{String,Any}: The embedded resource dataannotations::Union{Nothing,Dict{String,Any}}: Optional annotations for the client_meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions
ModelContextProtocol.ResourceLink — Type
ResourceLink(; type::String="resource_link", uri::String, name::String,
description::Union{String,Nothing}=nothing,
mime_type::Union{String,Nothing}=nothing,
title::Union{String,Nothing}=nothing,
annotations::Union{Nothing,Dict{String,Any}}=nothing,
_meta::Union{Nothing,Dict{String,Any}}=nothing) <: ContentLink to a resource a tool result can reference without embedding it (protocol 2025-06-18). Serialized per the MCP spec as {"type": "resource_link", "uri": ..., "name": ..., ...}.
Fields
type::String: Content type identifier (always "resource_link")uri::String: URI of the linked resourcename::String: Name of the resourcedescription::Union{String,Nothing}: Optional description of the resourcemime_type::Union{String,Nothing}: Optional MIME type, serialized asmimeTypesize::Union{Int,Nothing}: Optional resource size in bytestitle::Union{String,Nothing}: Optional human-readable titleannotations::Union{Nothing,Dict{String,Any}}: Optional annotations for the client_meta::Union{Nothing,Dict{String,Any}}: Optional metadata for protocol extensions
Resource Content Types
ModelContextProtocol.TextResourceContents — Type
TextResourceContents(; uri::URI, mime_type::String="text/plain", text::String) <: ResourceContentsText content for resources in the MCP protocol.
Fields
uri::URI: Resource identifiermime_type::String: MIME type of the text contenttext::String: The actual text content
ModelContextProtocol.BlobResourceContents — Type
BlobResourceContents(; uri::URI, mime_type::String="application/octet-stream",
blob::Vector{UInt8}) <: ResourceContentsBinary content for resources.
Fields
uri::URI: Resource identifiermime_type::String: MIME type of the binary contentblob::Vector{UInt8}: Raw binary data (automatically base64-encoded when serialized)
Tool Results
ModelContextProtocol.CallToolResult — Type
CallToolResult(; content::Vector{Dict{String,Any}}, is_error::Bool=false,
structured_content=nothing) <: ResponseResultResult returned from a tool invocation.
Fields
content::Vector{Dict{String,Any}}: Content produced by the toolis_error::Bool: Whether the tool execution resulted in an errorstructured_content::Union{Nothing,AbstractDict}: Optional structured result (a JSON object per the MCP spec), serialized asstructuredContentand omitted whennothing. Pair it with the tool'soutput_schemaso clients can validate and consume it programmatically. Per the spec, a tool returning structured content SHOULD also include a human-readable serialization (e.g. the JSON as text) incontentfor clients that don't consume structured output._meta::Union{Nothing,AbstractDict}: Optional result metadata for protocol extensions, serialized as_metaand omitted whennothing
Transport Configuration
ModelContextProtocol.Transport — Type
TransportAbstract base type for all MCP transport implementations. Defines the interface for reading and writing messages between client and server.
ModelContextProtocol.StdioTransport — Type
StdioTransport(; input::IO=stdin, output::IO=stdout)Transport implementation using standard input/output streams. This is the default transport for local MCP server processes.
Fields
input::IO: Input stream for reading messages (default: stdin)output::IO: Output stream for writing messages (default: stdout)connected::Bool: Connection status (always true for stdio)write_lock::ReentrantLock: Serializes output writes (responses and notifications share stdout, and background task executions may write concurrently with the loop)
ModelContextProtocol.HttpTransport — Type
HttpTransport(; host::String="127.0.0.1", port::Int=8080, endpoint::String="/",
allowed_origins::Vector{String}=String[], allowed_hosts::Vector{String}=String[])Transport implementation following the MCP Streamable HTTP specification (2025-06-18). Supports Server-Sent Events (SSE) for streaming and session management. A request's response is a single JSON object, or — when request-scoped notifications (progress, log messages) are emitted during handling — an SSE stream scoped to that request.
When bound to a loopback host without bearer auth, requests whose Host or Origin header is neither local nor allowlisted are rejected with 403 (DNS-rebinding protection); a deployment behind a reverse proxy adds its public hostname to allowed_hosts (or enables auth, which disables the guard).
Fields
host::String: Host address to bind to (default: "127.0.0.1")port::Int: Port number to listen on (default: 8080)endpoint::String: HTTP endpoint path (default: "/")server::Union{HTTP.Server,Nothing}: HTTP server instanceconnected::Bool: Connection statusserver_task::Union{Task,Nothing}: Server task handleactive_streams::Dict{String,HTTP.Stream}: Active streaming connectionsrequest_queue::Channel{QueuedHttpRequest}: Queue for incoming requests (id, body, auth user)response_channels::Dict{String,Channel{Tuple{Symbol,String}}}: Per-request response routes carrying(:notification, json)entries followed by one(:response, json)allowed_origins::Vector{String}: Origins accepted by the DNS-rebinding guard (exact match)allowed_hosts::Vector{String}: Extra Host-header hostnames accepted by the DNS-rebinding guard
ModelContextProtocol.connect — Function
connect(transport::Transport) -> NothingEstablish the transport connection. Default implementation does nothing (for transports that are always connected).
Arguments
transport::Transport: The transport instance to connect
Returns
Nothing
Throws
TransportError: If connection cannot be established
connect(transport::HttpTransport) -> NothingStart the HTTP server and begin listening for connections.
Arguments
transport::HttpTransport: The transport instance
Returns
Nothing
Throws
TransportError: If the server cannot be started
Server Type
ModelContextProtocol.Server — Type
Server(config::ServerConfig; transport::Union{Transport,Nothing}=nothing)Represent a running MCP server instance that manages resources, tools, and prompts.
Fields
config::ServerConfig: Server configuration settingstransport::Union{Transport,Nothing}: Transport implementation for client-server communicationresources::Vector{Resource}: Available resourcestools::Vector{Tool}: Available toolsprompts::Vector{MCPPrompt}: Available promptsresource_templates::Vector{ResourceTemplate}: Available resource templatessubscriptions::DefaultDict{String,Vector{Subscription}}: Resource subscription registryprogress_trackers::Dict{Union{String,Int},Progress}: Progress tracking for operationstasks::TaskStore: Registry of server-side tasks (MCP Tasks, experimental)listen_subscriptions::SubscriptionRegistry: Active modern-erasubscriptions/listenstreamsactive::Bool: Whether the server is currently activetask_notification_queue::Union{Channel{Any},Nothing}:notifications/tasksdispatch FIFO (set byinstall_task_notifications!, closed bystop!)tool_header_paths::Dict{String,Vector{Tuple{Vector{String},String}}}: per-tool SEP-2243 mirror tables — derived from the normalized schema byvalidate_tool_headersand persisted byregister!, read by thehandle_modern_requestpreflight
Constructor
Server(config::ServerConfig; transport=nothing): Creates a new server with the specified configuration
Resource Subscriptions
ModelContextProtocol.subscribe! — Function
subscribe!(server::Server, uri::String, callback::Function) -> ServerSubscribe to updates for a specific resource identified by URI.
The callback is an in-process observer: notify_resource_updated invokes it as callback(uri) whenever that URI is announced as changed. It runs on the announcing task, its errors are logged and swallowed, and it sends nothing to clients on its own (client delivery is notify_resource_updated's job).
Arguments
server::Server: The server instanceuri::String: The resource URI to subscribe tocallback::Function: Called ascallback(uri::String)on each announced update
Returns
Server: The server instance for method chaining
ModelContextProtocol.unsubscribe! — Function
unsubscribe!(server::Server, uri::String, callback::Function) -> ServerRemove a subscription for a specific resource URI and callback function.
Arguments
server::Server: The server instanceuri::String: The resource URI to unsubscribe fromcallback::Function: The callback function to remove
Returns
Server: The server instance for method chaining
ModelContextProtocol.notify_list_changed — Function
notify_list_changed(server::Server, kind::Symbol) -> IntAnnounce that a list of server components changed, delivering notifications/{kind}/list_changed to every subscriptions/listen stream that subscribed to it and to the connected legacy session (when the corresponding listChanged capability is declared). Call this after mutating server.tools, server.prompts, or server.resources at runtime.
Only streams open at the time of the change are notified (there is no backlog).
Arguments
server::Server: The server whose lists changedkind::Symbol: One of:tools,:prompts,:resources
Returns
Int: How many delivery targets a transport handoff was attempted for —subscriptions/listenstreams plus the legacy session. Counts attempted handoffs, not enqueue or client receipt (a disconnected HTTP peer, or a full notification queue, drops silently).
ModelContextProtocol.notify_resource_updated — Function
notify_resource_updated(server::Server, uri::AbstractString) -> IntAnnounce that a resource's contents changed, delivering notifications/resources/updated to every subscriptions/listen stream that subscribed to that URI and to the connected legacy session when it subscribed via resources/subscribe. In-process callbacks registered with subscribe! for the URI are also invoked (with the URI as their only argument); callback errors are logged and do not affect client delivery or the returned count.
Arguments
server::Server: The server holding the resourceuri::AbstractString: The resource URI that changed
Returns
Int: How many delivery targets a transport handoff was attempted for —subscriptions/listenstreams plus the legacy session. Counts attempted handoffs, not enqueue or client receipt (a disconnected HTTP peer, or a full notification queue, drops silently).
Handler Context Helpers
ModelContextProtocol.send_progress — Function
send_progress(ctx::RequestContext, progress::Real;
total::Union{Real,Nothing}=nothing,
message::Union{String,Nothing}=nothing) -> BoolEmit an MCP notifications/progress for the current request. A tool handler that accepts the RequestContext (its second argument) can call this during a long operation to report progress.
Returns false (a no-op) when the client did not supply a progressToken, no transport is connected, or the call is a detachable modern-era task call (tasks extension: notifications/progress is not supported on tasks, and the spawned handler has no request stream to route them to), so it is always safe to call. Send an increasing progress; include total for a determinate bar and message for a status line.
ModelContextProtocol.task_cancelled — Function
task_cancelled(ctx) -> BoolCheck whether the current task-augmented execution has been cancelled by the client (via tasks/cancel). Long-running, context-aware tool handlers can poll this to stop work early; the discarded result is never delivered (cancelled tasks stay cancelled). Always false for ordinary (non-task) calls, so it is safe to call unconditionally.
handler = (args, ctx) -> begin
for chunk in work_chunks
task_cancelled(ctx) && return TextContent(text = "aborted")
process(chunk)
end
TextContent(text = "done")
endMulti Round-Trip Requests (MRTR)
ModelContextProtocol.InputRequired — Type
InputRequired(requests::AbstractDict; state=nothing)The value a handler returns when it needs client input to finish (MRTR, 2026-07-28): the request is answered with an InputRequiredResult carrying these input requests, and the client retries with responses under the same keys. On the retry the handler runs AGAIN from the top — read the responses with input_responses(ctx) and any carried-over state with input_state(ctx).
Only meaningful on modern-era tools/call (legacy sessions have no wire shape for it and get an error). If a needed response is still missing on the retry, return another InputRequired — the spec says re-issue, not error.
A valid requestState can be replayed within its TTL (one-time semantics would require server-side shared state, which the stateless design avoids), so handlers should stay idempotent across retries.
Fields
requests::LittleDict{String,InputRequest}: server-assigned unique keys → input requestsstate::Any: JSON-serializable handler state to carry to the retry, delivered inside the integrity-protectedrequestState(do NOT put secrets here: it is signed, not encrypted)
ModelContextProtocol.elicit_request — Function
elicit_request(message::String; requested_schema=nothing) -> InputRequestBuild a form-mode elicitation input request (elicitation/create): ask the user a question, constraining the answer with a requested schema. The schema is REQUIRED on the wire (ElicitRequestFormParams.requestedSchema, an object schema with properties), so when none is given a minimal empty-object schema is synthesized — a schema-validating client would reject the request otherwise.
Arguments
message::String: The message to present to the userrequested_schema: JSON schema (Dict) for the expected response content; must be an object schema. Defaults to{"type": "object", "properties": {}}
Returns
InputRequest: The request for anInputRequiredreturn
ModelContextProtocol.sampling_request — Function
sampling_request(params::AbstractDict) -> InputRequestBuild a sampling input request (sampling/createMessage): ask the client's LLM for a completion. params is the CreateMessageRequest params object (e.g. messages, maxTokens).
Arguments
params::AbstractDict: Thesampling/createMessageparams
Returns
InputRequest: The request for anInputRequiredreturn
ModelContextProtocol.roots_request — Function
roots_request() -> InputRequestBuild a roots input request (roots/list): ask the client for its filesystem roots.
Returns
InputRequest: The request for anInputRequiredreturn
ModelContextProtocol.input_responses — Function
input_responses(ctx) -> Dict{String,Any}The client's inputResponses from an MRTR retry (2026-07-28), keyed like the inputRequests the server issued. Empty on a first (non-retry) request — a handler asks for input by returning InputRequired when the response it needs is absent.
Arguments
ctx: The request context passed to a ctx-aware handler
Returns
Dict{String,Any}: The responses (empty when none)
ModelContextProtocol.input_state — Function
input_state(ctx) -> AnyThe handler state carried through the verified requestState of an MRTR retry (whatever the handler put in InputRequired(...; state=...)), or nothing on a first request.
Arguments
ctx: The request context passed to a ctx-aware handler
Returns
- The carried state, or
nothing
Tasks Extension
ModelContextProtocol.task_detach — Function
task_detach(ctx; ttl_ms=nothing, status_message=nothing) -> BoolHand the current tool call off to background task execution (MCP Tasks extension, SEP-2663). Callable from a ctx-aware tool handler: when the request is modern-era, the tool is task-capable (task_support :optional or :required), and the client declared the io.modelcontextprotocol/tasks extension, this durably creates the task and immediately delivers the CreateTaskResult (resultType:"task") as the call's response — the handler keeps running in the background, and its eventual return value (or thrown error) becomes the task's terminal state, observable via tasks/get.
Returns false — and the handler simply continues as an ordinary synchronous call — when any precondition is absent (legacy-era request, extension not declared, tool not task-capable). Idempotent: a second call returns true without creating another task.
Arguments
ctx: The request context passed to a ctx-aware handlerttl_ms::Union{Int,Nothing}: Requested retention duration (clamped to the store's maximum);nothingfor the server defaultstatus_message::Union{String,Nothing}: Optional initialstatusMessage
Returns
Bool:truewhen the call is (now) task-detached
ModelContextProtocol.task_await_input — Function
task_await_input(ctx, request::InputRequest) -> Any
task_await_input(ctx, requests::AbstractVector{InputRequest}) -> Vector{Any}Ask the client for input MID-TASK and block the handler until it answers (tasks extension, SEP-2663). Callable from a handler that has already detached via task_detach: the request(s) are registered under server-minted keys (unique over the task's lifetime), the task's status flips to input_required, and tasks/get surfaces the outstanding requests in inputRequests. The client answers with tasks/update inputResponses; each response value is returned to the waiting handler (the vector form returns responses in request order, and only once ALL of them have arrived — a partial tasks/update is accepted, the task simply stays input_required until the rest arrive). Once nothing is pending the status returns to working.
Build requests with elicit_request, sampling_request, or roots_request — the same constructors the MRTR flow uses. A server MUST NOT send input requests the creating request's client capabilities did not declare, so an undeclared capability throws (failing the task).
Throws TaskCancelledException when the task goes terminal while (or before) waiting. An unanswered request blocks until the client answers or cancels, or until the task's ttl elapses — a per-wait deadline timer fails an expired task still parked on client input and unwinds its waiters, so abandoned tasks cannot pin handler state forever. To distinguish expiry from a client cancel, check task_cancelled(ctx) — true only for the latter.
The registered requests are frozen: each request's params are normalized into an owned plain-JSON snapshot at registration, so a key's content can never change across polls (the spec's key-stability rule) and the capability check binds to exactly what will be surfaced. Params must therefore be plain JSON data — nested dicts/vectors/tuples/sets of strings, numbers, booleans, and nothing (what elicit_request and friends naturally produce); anything else is rejected with an ArgumentError.
Before detachment there is no inputRequests surface: a handler that needs input to DECIDE (e.g. whether to proceed at all) returns InputRequired for the MRTR round on the original request instead.
Arguments
ctx: The request context passed to a ctx-aware handlerrequest/requests: The input request(s) to surface to the client
Returns
- The client's response value (single form), or a
Vector{Any}of response values in request order (vector form)
ModelContextProtocol.TaskCancelledException — Type
TaskCancelledException()Thrown by task_await_input when the task reaches a terminal state while the handler is waiting (or had already reached one when it asked) — cancelled by the client via tasks/cancel, or failed by the server because its ttl elapsed while parked on client input. Handlers that need to distinguish the two can check task_cancelled(ctx), which is true only for a client cancellation. Catch it for cleanup; otherwise it unwinds the handler, whose discarded outcome never overwrites the terminal status.
Protocol Version Negotiation
ModelContextProtocol.LATEST_PROTOCOL_VERSION — Constant
Latest LEGACY (initialize-handshake) MCP protocol version supported by this implementation. Modern-era versions live in MODERN_PROTOCOL_VERSIONS.
ModelContextProtocol.SUPPORTED_PROTOCOL_VERSIONS — Constant
All LEGACY (initialize-handshake) MCP protocol versions supported by this implementation, newest first. These are the versions initialize negotiates; modern-era versions (per-request _meta, no handshake) live in MODERN_PROTOCOL_VERSIONS.
ModelContextProtocol.FEATURE_VERSIONS — Constant
Minimum protocol version required for each feature.
Features are identified by Symbol keys. The value is the minimum protocol version that introduced the feature. Use supports(version, feature) to check availability.
Features
:tasks- Experimental task tracking (SEP-1686):sse_priming_events- SSE priming for stream resumability (SEP-1699):icon_metadata- Icon metadata for tools/resources/prompts (SEP-973):tool_calling_in_sampling- Tool calling in sampling requests (SEP-1577):oauth_openid_connect- OpenID Connect discovery for OAuth (PR #797):oauth_incremental_scope- Incremental scope consent (SEP-835):url_elicitation- URL mode elicitation requests (SEP-1036):streamable_http- Streamable HTTP transport:resource_links- ResourceLink content type
ModelContextProtocol.negotiate_version — Function
negotiate_version(client_version::Union{AbstractString, Nothing}) -> StringNegotiate the protocol version with a client per the MCP specification.
If the client requests a version we support, return that version. Otherwise, return our latest version and let the client decide whether it can proceed.
Arguments
client_version::Union{AbstractString, Nothing}: Protocol version requested by the client, or nothing
Returns
String: The negotiated protocol version
ModelContextProtocol.supports — Function
supports(version::AbstractString, feature::Symbol) -> BoolCheck whether a protocol version supports a specific feature.
Arguments
version::AbstractString: The negotiated protocol versionfeature::Symbol: Feature identifier (seeFEATURE_VERSIONSfor available features)
Returns
Bool: true if the version supports the feature
Example
if supports(negotiated_version, :tasks)
# Include task tracking in response
endModelContextProtocol.is_supported_version — Function
is_supported_version(version::AbstractString) -> BoolCheck whether a protocol version is in our supported versions list.
Arguments
version::AbstractString: Protocol version string to check
Returns
Bool: true if we support this version
Authentication (OAuth Resource Server)
Configuration and Middleware
ModelContextProtocol.OAuthConfig — Type
OAuthConfig(; issuer::String, audience::String,
required_scopes::Vector{String}=String[],
jwks_uri::Union{String,Nothing}=nothing,
introspection_endpoint::Union{String,Nothing}=nothing)Configure OAuth 2.0 token validation for an MCP server.
Fields
issuer::String: Expected token issuer (iss claim)audience::String: Expected audience (aud claim) - typically your server's URLrequired_scopes::Vector{String}: Scopes required to access the serverjwks_uri::Union{String,Nothing}: URL to fetch JSON Web Key Set for JWT validationintrospection_endpoint::Union{String,Nothing}: Token introspection endpoint URL
ModelContextProtocol.AuthMiddleware — Type
AuthMiddleware(; config::OAuthConfig,
validator::TokenValidator,
allowlist::Union{Set{String},Nothing}=nothing,
case_insensitive_allowlist::Bool=true,
enabled::Bool=true)Middleware for authenticating HTTP requests to an MCP server.
Fields
config::OAuthConfig: OAuth configurationvalidator::TokenValidator: Token validation strategyallowlist::Union{Set{String},Nothing}: Optional set of allowed usernames/subjectscase_insensitive_allowlist::Bool: Whentrue(default), allowlist username matching is case-insensitive (identity providers vary/normalize case — e.g. Keycloak lowercases GitHub logins); the opaque OAuthsubjectis always matched exactly. Setfalsefor exact username matching.enabled::Bool: Whether authentication is enabled (for development/testing)
ModelContextProtocol.AuthResult — Type
AuthResultResult of an authentication attempt.
ModelContextProtocol.AuthenticatedUser — Type
AuthenticatedUser(; subject::String, provider::String,
username::Union{String,Nothing}=nothing,
scopes::Vector{String}=String[],
claims::Dict{String,Any}=Dict{String,Any}())Represent an authenticated user after successful token validation.
Fields
subject::String: Unique user identifier (sub claim from token)provider::String: Authentication provider name (e.g., "github", "google")username::Union{String,Nothing}: Human-readable username if availablescopes::Vector{String}: Granted OAuth scopesclaims::Dict{String,Any}: Raw claims from the token
ModelContextProtocol.create_auth_middleware — Function
create_auth_middleware(config::OAuthConfig;
validator::TokenValidator,
allowlist::Union{Set{String},Nothing}=nothing,
enabled::Bool=true) -> AuthMiddlewareCreate an authentication middleware for the HTTP transport.
Arguments
config::OAuthConfig: OAuth configurationvalidator::TokenValidator: Token validation strategy (REQUIRED — no default, so an unsafe validator is never selected implicitly. NoteJWTValidatordoes not verify signatures; preferIntrospectionValidatororGitHubOAuthValidatorfor tokens from external issuers.)allowlist::Union{Set{String},Nothing}: Optional allowlist of usernames/subjectsenabled::Bool: Whether auth is enabled (default: true)
Example
auth = create_auth_middleware(
OAuthConfig(
issuer = "https://github.com",
audience = "my-mcp-server"
),
validator = IntrospectionValidator(client_id = "id", client_secret = "secret"),
allowlist = Set(["user1", "user2"])
)ModelContextProtocol.create_simple_auth — Function
create_simple_auth(tokens::Dict{String,String};
allowlist::Union{Set{String},Nothing}=nothing) -> AuthMiddlewareCreate a simple API key-based authentication middleware.
Arguments
tokens::Dict{String,String}: Map of API keys to usernamesallowlist::Union{Set{String},Nothing}: Optional additional allowlist
Example
auth = create_simple_auth(Dict(
"sk-abc123" => "user1",
"sk-def456" => "user2"
))ModelContextProtocol.disable_auth — Function
disable_auth() -> AuthMiddlewareCreate a disabled auth middleware (for development/testing). All requests will be allowed with an anonymous user.
ModelContextProtocol.is_auth_enabled — Function
is_auth_enabled(transport::HttpTransport) -> BoolReturn whether OAuth Resource Server token validation is enabled on this transport.
Arguments
transport::HttpTransport: The transport instance
Returns
Bool: true if an enabledAuthMiddlewareis configured
Token Validators
ModelContextProtocol.AuthProvider — Type
AuthProviderAbstract type for authentication providers (GitHub, Google, custom OAuth servers).
ModelContextProtocol.TokenValidator — Type
TokenValidatorAbstract type for token validation strategies (JWT, introspection).
ModelContextProtocol.SimpleTokenValidator — Type
SimpleTokenValidator(; tokens::Dict{String,AuthenticatedUser})Simple token validator using a static mapping of tokens to users. Useful for API keys and development/testing.
Lookups are plain dictionary comparisons (not constant-time) and tokens are held in memory in plaintext. Intended for development and trusted static API keys, not as a general-purpose production token store.
Fields
tokens::Dict{String,AuthenticatedUser}: Map of valid tokens to user info
ModelContextProtocol.JWTValidator — Type
JWTValidator(; insecure_skip_signature_verification::Bool, clock_skew_seconds::Int=60)JWT validator that checks claims (iss, aud, exp, nbf, scope) but does not verify the token's cryptographic signature.
This validator decodes and validates JWT claims but does not verify the token's cryptographic signature, so any caller can forge the issuer, audience, and scopes. It therefore refuses to construct unless you pass insecure_skip_signature_verification = true.
For tokens from an authorization server, use JWKSValidator (signature verification via JWKS — the recommended path) or IntrospectionValidator (RFC 7662). Choose JWTValidator only when this server sits behind a gateway that has already verified the signature.
Fields
jwks_cache::Dict{String,Any}: Unused (retained for struct-layout compatibility)clock_skew_seconds::Int: Allowed clock skew for exp/nbf validation
ModelContextProtocol.JWKSValidator — Type
JWKSValidator(jwks_uri::String; allowed_algs=["RS256", "RS384", "RS512"],
clock_skew_seconds=60, refresh_interval_seconds=300,
allow_insecure_http=false)
JWKSValidator(keyset::JWTs.JWKSet; ...)JWT validator with cryptographic signature verification against a JSON Web Key Set (RFC 7517), plus the same claims validation as JWTValidator (iss, aud, exp, nbf, scopes — all fail-closed). This is the recommended validator for JWTs from external authorization servers (Keycloak, Auth0, GitHub Apps, etc.).
Keys are fetched lazily: construction never touches the network, so a server can start while its authorization server is down (requests fail closed until keys load). An unknown kid triggers a JWKS re-fetch (key rotation) at most once per refresh_interval_seconds — rate-limited so attacker-supplied kid values cannot hammer the JWKS endpoint. Fetches use bounded HTTP timeouts and a response size cap (MAX_JWKS_BYTES), and never hold the validator lock during network I/O.
file:// URIs are supported for local key sets. An http:// URL is rejected at construction unless allow_insecure_http=true (a plaintext JWKS lets an on-path attacker swap in their own signing key — use only for localhost/testing). The second constructor accepts a pre-built JWTs.JWKSet (e.g. static keys) directly; with no URL it never refreshes.
Tokens whose header alg is not in allowed_algs are rejected before any cryptography runs (this also rejects alg=none). The default allows the RSA family only; do not add HMAC algorithms (HS*) for keys published in a public JWKS document.
Fields
keyset::JWTs.JWKSet: Key set (url-backed or static) holding keys bykidallowed_algs::Vector{String}: Permitted JWT signature algorithmsclock_skew_seconds::Int: Allowed clock skew for exp/nbf validationrefresh_interval_seconds::Float64: Minimum seconds between JWKS fetch attempts (>= 0)
ModelContextProtocol.IntrospectionValidator — Type
IntrospectionValidator(; client_id=nothing, client_secret=nothing)Token validator using OAuth 2.0 Token Introspection (RFC 7662). Used for opaque tokens that cannot be validated locally.
Fields
client_id::Union{String,Nothing}: Client ID for introspection authclient_secret::Union{String,Nothing}: Client secret for introspection auth
ModelContextProtocol.GitHubOAuthValidator — Type
GitHubOAuthValidator(; cache_ttl_seconds::Int=300)Token validator for GitHub OAuth access tokens. Validates tokens by calling GitHub's /user API endpoint.
Fields
cache_ttl_seconds::Int: How long to cache user info (default: 5 minutes)user_cache::Dict{String,Tuple{AuthenticatedUser,DateTime}}: Cache of validated tokenscache_lock::ReentrantLock: Lock for thread-safe cache access
ModelContextProtocol.create_github_auth — Function
create_github_auth(; allowed_users::Union{Vector{String},Set{String}}=String[],
required_org::Union{String,Nothing}=nothing,
cache_ttl_seconds::Int=300) -> AuthMiddlewareCreate an authentication middleware configured for GitHub OAuth.
Arguments
allowed_users: List of GitHub usernames allowed to access the serverrequired_org: Optionally require membership in a GitHub organizationcache_ttl_seconds: How long to cache validated tokens (default: 5 minutes)
Returns
AuthMiddleware configured for GitHub OAuth validation.
Example
# Allow specific users
auth = create_github_auth(
allowed_users = ["user1", "user2", "user3"]
)
# Require organization membership
auth = create_github_auth(
required_org = "JuliaSMLM"
)
# Both user allowlist and org requirement
auth = create_github_auth(
allowed_users = ["user1", "user2"],
required_org = "LidkeLab"
)ModelContextProtocol.clear_cache! — Function
clear_cache!(validator::GitHubOAuthValidator)Clear the token validation cache.
Protected Resource Metadata (RFC 9728)
ModelContextProtocol.ProtectedResourceMetadata — Type
ProtectedResourceMetadata(; resource::String,
authorization_servers::Vector{String},
scopes_supported::Vector{String}=String[],
bearer_methods_supported::Vector{String}=["header"])MCP Protected Resource Metadata per RFC 9728. Served at .well-known/oauth-protected-resource.
Fields
resource::String: The protected resource identifier (your server URL)authorization_servers::Vector{String}: URLs of authorization servers that can issue tokensscopes_supported::Vector{String}: OAuth scopes the resource understandsbearer_methods_supported::Vector{String}: How tokens can be sent (header, body, query)
ModelContextProtocol.create_protected_resource_metadata — Function
create_protected_resource_metadata(resource_url::String,
authorization_servers::Vector{String};
scopes::Vector{String}=String[]) -> ProtectedResourceMetadataCreate Protected Resource Metadata for the MCP server.
Arguments
resource_url::String: The URL of your MCP server (the protected resource)authorization_servers::Vector{String}: URLs of OAuth authorization serversscopes::Vector{String}: OAuth scopes the server understands
Example
metadata = create_protected_resource_metadata(
"https://mcp.example.com",
["https://github.com/login/oauth"],
scopes = ["read:user", "repo"]
)ModelContextProtocol.create_github_resource_metadata — Function
create_github_resource_metadata(resource_url::String;
scopes::Vector{String}=["read:user"]) -> ProtectedResourceMetadataCreate Protected Resource Metadata configured for GitHub OAuth.
Arguments
resource_url::String: Your MCP server URLscopes::Vector{String}: GitHub OAuth scopes to request (default: ["read:user"])
Example
metadata = create_github_resource_metadata(
"https://mcp.lidkelab.org",
scopes = ["read:user", "read:org"]
)Request Authentication
ModelContextProtocol.authenticate_request — Function
authenticate_request(middleware::AuthMiddleware, authorization_header::Union{String,Nothing}) -> AuthResultAuthenticate an HTTP request using the auth middleware.
Arguments
middleware::AuthMiddleware: The authentication middlewareauthorization_header::Union{String,Nothing}: The Authorization header value
Returns
AuthResult indicating success with user info, or failure with error details.
ModelContextProtocol.validate_token — Function
validate_token(validator::TokenValidator, token::AbstractString, config::OAuthConfig) -> AuthResultValidate an OAuth token using the specified validator.
Arguments
validator::TokenValidator: The validation strategy to usetoken::AbstractString: The token to validateconfig::OAuthConfig: OAuth configuration with expected issuer, audience, etc.
Returns
AuthResult: Success with user info, or failure with error details
ModelContextProtocol.extract_bearer_token — Function
extract_bearer_token(authorization_header::String) -> Union{String,Nothing}Extract Bearer token from Authorization header.
Arguments
authorization_header::String: The Authorization header value
Returns
The token if present and valid format, nothing otherwise.
Utility Functions
ModelContextProtocol.content2dict — Function
content2dict(content::Content) -> Dict{String,Any}Convert a Content object to its dictionary representation for JSON serialization.
Arguments
content::Content: The content object to convert
Returns
Dict{String,Any}: Dictionary representation of the content
Examples
text_content = TextContent(text="Hello", type="text")
dict = content2dict(text_content)
# Returns: Dict("type" => "text", "text" => "Hello", "annotations" => Dict())Transport Options
ModelContextProtocol.jl supports multiple transport mechanisms:
STDIO Transport (Default)
server = mcp_server(name = "my-server")
start!(server) # Uses StdioTransport by defaultHTTP Transport
server = mcp_server(name = "my-http-server")
transport = HttpTransport(; port = 3000)
connect(transport) # binds the port and starts the listener
start!(server; transport = transport)
# With custom configuration
transport = HttpTransport(;
host = "127.0.0.1", # Important for Windows
port = 8080, # Default port
endpoint = "/" # Default endpoint
)
connect(transport)
start!(server; transport = transport)Note: HTTP transport currently supports HTTP only, not HTTPS. For production use:
- Use
mcp-remotewith--allow-httpflag for secure connections - Or deploy behind a reverse proxy (nginx, Apache) for TLS termination
Internal API
The following internal types and functions are documented for developers working on the package itself.
Protocol Types
ModelContextProtocol.CallToolParams — Type
CallToolParams(; name::String, arguments::Union{Dict{String,Any},Nothing}=nothing) <: RequestParamsParameters for invoking a specific tool on an MCP server.
Fields
name::String: Name of the tool to callarguments::Union{Dict{String,Any},Nothing}: Optional arguments to pass to the tooltask::Union{Dict{String,Any},Nothing}: When present, the caller requests task-augmented execution (MCP Tasks, experimental); may carry a requested"ttl"in milliseconds
ModelContextProtocol.CancelTaskParams — Type
CancelTaskParams(; taskId::String) <: RequestParamsParameters for a tasks/cancel request.
Fields
taskId::String: The task identifier to cancel
ModelContextProtocol.ClientCapabilities — Type
ClientCapabilities(; experimental::Union{Dict{String,Dict{String,Any}},Nothing}=nothing,
roots::Union{Dict{String,Bool},Nothing}=nothing,
sampling::Union{Dict{String,Any},Nothing}=nothing)Capabilities reported by an MCP client during initialization.
Fields
experimental::Union{Dict{String,Dict{String,Any}},Nothing}: Experimental features supportedroots::Union{Dict{String,Bool},Nothing}: Root directories client has access tosampling::Union{Dict{String,Any},Nothing}: Sampling capabilities for model generation
ModelContextProtocol.CompleteParams — Type
CompleteParams(; ref::CompletionReference, argument::CompletionArgument,
context::Union{Dict{String,Any},Nothing}=nothing) <: RequestParamsParameters for a completion/complete request.
Fields
ref::CompletionReference: The prompt or resource template being completedargument::CompletionArgument: The argument name and partial valuecontext::Union{Dict{String,Any},Nothing}: Optional context; itsargumentsentry carries already-resolved argument values
ModelContextProtocol.CompletionArgument — Type
CompletionArgument(; name::String, value::String)Name the argument being completed and the partial value typed so far.
Fields
name::String: The argument (or template variable) namevalue::String: The partial value to complete
ModelContextProtocol.CompletionReference — Type
CompletionReference(; type::String, name::Union{String,Nothing}=nothing,
uri::Union{String,Nothing}=nothing)Identify what a completion/complete request targets: a prompt (type of ref/prompt with name) or a resource template (type of ref/resource with uri naming the URI template).
Fields
type::String:"ref/prompt"or"ref/resource"name::Union{String,Nothing}: The prompt name (forref/prompt)uri::Union{String,Nothing}: The URI template (forref/resource)
ModelContextProtocol.ErrorInfo — Type
ErrorInfo(; code::Int, message::String, data::Union{Dict{String,Any},Nothing}=nothing)Error information structure for JSON-RPC error responses.
Fields
code::Int: Numeric error code (predefined in ErrorCodes module)message::String: Human-readable error descriptiondata::Union{Dict{String,Any},Nothing}: Optional additional error details
ModelContextProtocol.GetPromptParams — Type
GetPromptParams(; name::String, arguments::Union{Dict{String,String},Nothing}=nothing) <: RequestParamsParameters for requesting a specific prompt from an MCP server.
Fields
name::String: Name of the prompt to retrievearguments::Union{Dict{String,String},Nothing}: Optional arguments to apply to the prompt template
ModelContextProtocol.GetPromptResult — Type
GetPromptResult(; description::String, messages::Vector{PromptMessage}) <: ResponseResultResult returned from a get prompt request.
Fields
description::String: Description of the promptmessages::Vector{PromptMessage}: The prompt messages with template variables replaced
ModelContextProtocol.GetTaskParams — Type
GetTaskParams(; taskId::String) <: RequestParamsParameters for a tasks/get status poll.
Fields
taskId::String: The task identifier to query
ModelContextProtocol.Implementation — Type
Implementation(; name::String="default-client", version::String="1.0.0",
title::Union{String,Nothing}=nothing,
description::Union{String,Nothing}=nothing)Information about a client or server implementation of the MCP protocol.
Fields
name::String: Name of the implementationversion::String: Version string of the implementationtitle::Union{String,Nothing}: Optional human-readable display namedescription::Union{String,Nothing}: Optional human-readable description (MCP 2025-11-25)
ModelContextProtocol.InitializeParams — Type
InitializeParams(; capabilities::ClientCapabilities=ClientCapabilities(),
clientInfo::Implementation=Implementation(),
protocolVersion::Union{String,Nothing}=nothing) <: RequestParamsParameters for MCP protocol initialization requests.
Fields
capabilities::ClientCapabilities: Client capabilities being reportedclientInfo::Implementation: Information about the client implementationprotocolVersion::Union{String,Nothing}: Version of the MCP protocol requested by the client. The server negotiates againstSUPPORTED_PROTOCOL_VERSIONS(latest:LATEST_PROTOCOL_VERSION); seenegotiate_version.
ModelContextProtocol.InitializeResult — Type
InitializeResult(; serverInfo::Dict{String,Any}, capabilities::Dict{String,Any},
protocolVersion::String, instructions::String="") <: ResponseResultResult returned in response to MCP protocol initialization.
Fields
serverInfo::Dict{String,Any}: Information about the server implementationcapabilities::Dict{String,Any}: Server capabilities being reportedprotocolVersion::String: Version of the MCP protocol being usedinstructions::String: Optional usage instructions for clients
ModelContextProtocol.JSONRPCError — Type
JSONRPCError(; id::Union{RequestId,Nothing}, error::ErrorInfo) <: ResponseJSON-RPC error response message returned when requests fail.
Fields
id::Union{RequestId,Nothing}: Identifier matching the request this is responding to, or nullerror::ErrorInfo: Information about the error that occurred
ModelContextProtocol.JSONRPCNotification — Type
JSONRPCNotification(; method::String,
params::Union{RequestParams,Dict{String,Any}}) <: NotificationJSON-RPC notification message that does not expect a response.
Fields
method::String: Name of the notification methodparams::Union{RequestParams,Dict{String,Any}}: Parameters for the notification
ModelContextProtocol.JSONRPCRequest — Type
JSONRPCRequest(; id::RequestId, method::String,
params::Union{RequestParams, Nothing},
meta::RequestMeta=RequestMeta()) <: RequestJSON-RPC request message used to invoke methods on the server.
Fields
id::RequestId: Unique identifier for the requestmethod::String: Name of the method to invokeparams::Union{RequestParams, Nothing}: Parameters for the methodmeta::RequestMeta: Additional metadata for the request
ModelContextProtocol.JSONRPCResponse — Type
JSONRPCResponse(; id::RequestId, result::Union{ResponseResult,AbstractDict{String,Any}}) <: ResponseJSON-RPC response message returned for successful requests.
Fields
id::RequestId: Identifier matching the request this is responding toresult::Union{ResponseResult,AbstractDict{String,Any}}: Results of the method execution
ModelContextProtocol.ListPromptsParams — Type
ListPromptsParams(; cursor::Union{String,Nothing}=nothing) <: RequestParamsParameters for requesting a list of available prompts from an MCP server.
Fields
cursor::Union{String,Nothing}: Optional pagination cursor for long prompt lists
ModelContextProtocol.ListPromptsResult — Type
ListPromptsResult(; prompts::Vector{Dict{String,Any}},
nextCursor::Union{String,Nothing}=nothing) <: ResponseResultResult returned from a list prompts request.
Fields
prompts::Vector{Dict{String,Any}}: List of available prompts with their metadatanextCursor::Union{String,Nothing}: Optional pagination cursor for fetching more prompts
ModelContextProtocol.ListResourceTemplatesParams — Type
ListResourceTemplatesParams(; cursor::Union{String,Nothing}=nothing) <: RequestParamsParameters for a resources/templates/list request.
Fields
cursor::Union{String,Nothing}: Optional pagination cursor for long template lists
ModelContextProtocol.ListResourcesParams — Type
ListResourcesParams(; cursor::Union{String,Nothing}=nothing) <: RequestParamsParameters for requesting a list of available resources from an MCP server.
Fields
cursor::Union{String,Nothing}: Optional pagination cursor for long resource lists
ModelContextProtocol.ListResourcesResult — Type
ListResourcesResult(; resources::Vector{Dict{String,Any}},
nextCursor::Union{String,Nothing}=nothing) <: ResponseResultResult returned from a list resources request.
Fields
resources::Vector{Dict{String,Any}}: List of available resources with their metadatanextCursor::Union{String,Nothing}: Optional pagination cursor for fetching more resources
ModelContextProtocol.ListTasksParams — Type
ListTasksParams(; cursor::Union{String,Nothing}=nothing) <: RequestParamsParameters for a paginated tasks/list request.
Fields
cursor::Union{String,Nothing}: Opaque pagination cursor from a previous response
ModelContextProtocol.ListToolsParams — Type
ListToolsParams(; cursor::Union{String,Nothing}=nothing) <: RequestParamsParameters for requesting a list of available tools from an MCP server.
Fields
cursor::Union{String,Nothing}: Optional pagination cursor for long tool lists
ModelContextProtocol.ListToolsResult — Type
ListToolsResult(; tools::Vector{Dict{String,Any}},
nextCursor::Union{String,Nothing}=nothing) <: ResponseResultResult returned from a list tools request.
Fields
tools::Vector{Dict{String,Any}}: List of available tools with their metadatanextCursor::Union{String,Nothing}: Optional pagination cursor for fetching more tools
ModelContextProtocol.ProgressParams — Type
ProgressParams(; progress_token::ProgressToken, progress::Float64,
total::Union{Float64,Nothing}=nothing) <: RequestParamsParameters for progress notifications during long-running operations.
Fields
progress_token::ProgressToken: Token identifying the operation being reported onprogress::Float64: Current progress valuetotal::Union{Float64,Nothing}: Optional total expected value
ModelContextProtocol.ReadResourceParams — Type
ReadResourceParams(; uri::String) <: RequestParamsParameters for requesting the contents of a specific resource.
Fields
uri::String: URI identifier of the resource to read
ModelContextProtocol.ReadResourceResult — Type
ReadResourceResult(; contents::Vector{Dict{String,Any}}) <: ResponseResultResult returned from a read resource request.
Fields
contents::Vector{Dict{String,Any}}: The contents of the requested resource
ModelContextProtocol.RequestMeta — Type
RequestMeta(; progress_token::Union{ProgressToken,Nothing}=nothing,
protocol_version::Union{String,Nothing}=nothing,
client_capabilities::Union{Dict{String,Any},Nothing}=nothing,
client_info::Union{Dict{String,Any},Nothing}=nothing)Metadata for MCP protocol requests: progress tracking, plus the modern-era (2026-07-28+) per-request protocol fields carried in _meta under io.modelcontextprotocol/* keys. A non-nothing protocol_version marks the request as modern-era (stateless, no initialize handshake) and routes it through handle_modern_request.
Fields
progress_token::Union{ProgressToken,Nothing}: Optional token for tracking request progressprotocol_version::Union{String,Nothing}:io.modelcontextprotocol/protocolVersion(required on every modern-era request; absent on legacy requests). Only string values are honored — a non-string value is treated as absent.client_capabilities::Any:io.modelcontextprotocol/clientCapabilities(required on every modern-era request), kept as the raw parsed JSON object — no re-encoding copy is madeclient_info::Any:io.modelcontextprotocol/clientInfo(optional), kept as the raw parsed JSON objectlog_level::Union{String,Nothing}:io.modelcontextprotocol/logLevel(optional) — the client's per-request opt-in tonotifications/messagedelivery. Only string values are stored; validation against the recognized levels happens inhandle_modern_requesthas_log_level::Bool: Whether thelogLevelkey was present at all. Presence is tracked separately from the typed value so a present-but-invalid level is REJECTED (-32602 per the spec), never silently treated as absent
ModelContextProtocol.SetLevelParams — Type
SetLevelParams(; level::String) <: RequestParamsParameters for logging/setLevel requests.
Fields
level::String: Minimum log level the client wants to receive (one of the MCP/RFC-5424 levels: "debug", "info", "notice", "warning", "error", "critical", "alert", "emergency")
ModelContextProtocol.SubscribeParams — Type
SubscribeParams(; uri::String) <: RequestParamsParameters for resources/subscribe requests.
Fields
uri::String: URI of the resource the client wants update notifications for
ModelContextProtocol.SubscriptionsListenParams — Type
SubscriptionsListenParams(; notifications::Union{Nothing,Dict{String,Any}}=nothing) <: RequestParamsParameters for subscriptions/listen requests (modern era).
Fields
notifications::Union{Nothing,Dict{String,Any}}: The notification-type filter —toolsListChanged/promptsListChanged/resourcesListChangedbooleans and aresourceSubscriptionsarray of resource URIs. Required: an absent or malformed filter is rejected with -32602 by the handler (seeparse_subscription_filter);nothinghere only represents the not-yet-validated wire state.
ModelContextProtocol.TaskResultParams — Type
TaskResultParams(; taskId::String) <: RequestParamsParameters for a tasks/result payload retrieval. The response blocks until the task reaches a terminal status and then matches the original request's result type.
Fields
taskId::String: The task identifier to retrieve results for
ModelContextProtocol.UnsubscribeParams — Type
UnsubscribeParams(; uri::String) <: RequestParamsParameters for resources/unsubscribe requests.
Fields
uri::String: URI of the resource to stop receiving update notifications for
ModelContextProtocol.UpdateTaskParams — Type
UpdateTaskParams(; taskId::String, inputResponses::Dict{String,Any}) <: RequestParamsParameters for a tasks/update request (tasks extension, SEP-2663): the client's responses to outstanding inputRequests surfaced by tasks/get on an input_required task. Both fields are required — a request missing either fails typed parsing and is rejected with -32602.
Fields
taskId::String: The task identifier to updateinputResponses::Dict{String,Any}: Responses keyed to match the server-issuedinputRequestskeys
ModelContextProtocol.get_params_type — Method
get_params_type(method::String) -> Union{Type,Nothing}Get the appropriate parameter type for a given JSON-RPC method name.
Arguments
method::String: The JSON-RPC method name
Returns
Union{Type,Nothing}: The Julia type to use for parsing parameters, ornothingif no specific type is defined
ModelContextProtocol.get_result_type — Method
get_result_type(id::RequestId) -> Union{Type{<:ResponseResult},Nothing}Get the expected result type for a response based on the request ID.
Arguments
id::RequestId: The request ID to look up
Returns
Union{Type{<:ResponseResult},Nothing}: The expected response result type, ornothingif not known
Note: This is a placeholder that needs to be implemented with request tracking.
ModelContextProtocol.parse_error_response — Method
parse_error_response(raw::JSON3.Object) -> ResponseParse a JSON-RPC error response object into a typed Response struct.
Arguments
raw::JSON3.Object: The parsed JSON object representing an error response
Returns
Response: A JSONRPCError with properly typed error information
ModelContextProtocol.parse_message — Method
parse_message(json::String) -> MCPMessageParse a JSON-RPC message string into the appropriate typed message object.
Arguments
json::String: The raw JSON-RPC message string
Returns
MCPMessage: A typed MCPMessage subtype (JSONRPCRequest, JSONRPCResponse, JSONRPCNotification, or JSONRPCError)
ModelContextProtocol.parse_notification — Method
parse_notification(raw::JSON3.Object) -> NotificationParse a JSON-RPC notification object into a typed Notification struct.
Arguments
raw::JSON3.Object: The parsed JSON object representing a notification
Returns
Notification: A JSONRPCNotification with properly typed parameters if possible
ModelContextProtocol.parse_request — Method
parse_request(raw::JSON3.Object) -> RequestParse a JSON-RPC request object into a typed Request struct.
Arguments
raw::JSON3.Object: The parsed JSON object representing a request
Returns
Request: A JSONRPCRequest with properly typed parameters based on the method
ModelContextProtocol.parse_success_response — Method
parse_success_response(raw::JSON3.Object) -> ResponseParse a successful JSON-RPC response object into a typed Response struct.
Arguments
raw::JSON3.Object: The parsed JSON object representing a successful response
Returns
Response: A JSONRPCResponse with properly typed result if possible, or JSONRPCError if parsing fails
ModelContextProtocol.serialize_message — Method
serialize_message(msg::MCPMessage) -> StringSerialize an MCP message object into a JSON-RPC compliant string.
Arguments
msg::MCPMessage: The message object to serialize (Request, Response, Notification, or Error)
Returns
String: A JSON string representation of the message following the JSON-RPC 2.0 specification
ModelContextProtocol.HandlerResult — Type
HandlerResult(; response::Union{Response,Nothing}=nothing,
error::Union{ErrorInfo,Nothing}=nothing)Represent the result of handling a request.
Fields
response::Union{Response,Nothing}: The response to send (if successful)error::Union{ErrorInfo,Nothing}: Error information (if request failed)deferred::Bool: When true, neither field is set and the response will be delivered out-of-loop viadeliver_response(used by the blockingtasks/result)
A HandlerResult must contain either a response, an error, or be deferred.
ModelContextProtocol.RequestContext — Type
RequestContext(; server::Server, state::ServerState=ServerState(),
request_id::Union{RequestId,Nothing}=nothing,
progress_token::Union{ProgressToken,Nothing}=nothing)Store the current request context for MCP protocol handlers.
Fields
server::Server: The MCP server instance handling the requeststate::ServerState: The persistent server state, carrying the negotiated protocol version for feature gating (seesupports)request_id::Union{RequestId,Nothing}: The ID of the current request (if any)progress_token::Union{ProgressToken,Nothing}: Optional token for progress reporting
ModelContextProtocol.RequestHandler — Type
RequestHandlerDefine base type for all request handlers.
ModelContextProtocol._json_integer_value — Method
_json_integer_value(s::AbstractString) -> Union{BigInt,Nothing}Evaluate a JSON-number token EXACTLY, returning its value when it denotes an integer: "42", "42.0", "4.2e1", and "-0.0" all evaluate (to 42, 42, 42, and 0), while non-numbers, non-integral values, and tokens with unreasonably large exponents (a "1e999999" mirror must not allocate a gigadigit BigInt) return nothing. Never goes through Float64, so distinct integers beyond 2^53 stay distinct.
ModelContextProtocol.completion_values — Method
completion_values(sources, arg_name::String, value::String,
context_args::Union{Nothing,Dict{String,String}}) -> Vector{String}Resolve the suggestion list for one completion request from a component's completions sources: a Vector source is served filtered by prefix against the partial value; a Function source is called as f(value) — or f(value, context_args) when applicable, where context_args is the request context's validated arguments map (already-resolved argument values) or nothing. Missing sources (or a component without any) resolve to no suggestions. Source misconfiguration — a non-Vector/non-Function source, a non-string element, or a function returning a lone string or non-strings — throws ArgumentError (surfaced by the handler as an internal error naming the cause) rather than silently coercing.
Arguments
sources: The component'scompletionsfield (a Dict ornothing)arg_name::String: The argument (or template variable) being completedvalue::String: The partial value typed so farcontext_args: The request context's validatedarguments, ornothing
Returns
Vector{String}: The full (uncapped) suggestion list
ModelContextProtocol.convert_to_content_type — Method
convert_to_content_type(result::Any) -> AnyApply the documented convenience conversions for tool handler return values: a Dict becomes JSON wrapped in TextContent, a String becomes TextContent, and a Tuple{Vector{UInt8},String} becomes ImageContent.
These conversions are independent of the tool's declared return_type (the caller validates the converted result against return_type afterwards), so the documented behavior holds for the default return_type = Vector{Content} too.
Arguments
result::Any: The raw value returned by a tool handler
Returns
Any: AContentobject for the convenience cases above; otherwiseresultunchanged
ModelContextProtocol.execute_tool_call — Method
execute_tool_call(tool::MCPTool, args::AbstractDict, ctx::RequestContext)
-> Union{CallToolResult,ErrorInfo}Run a tool handler and normalize its return value to a CallToolResult (applying the documented convenience conversions and return_type validation), an InputRequired (passed through verbatim for the MRTR layer to convert), or an ErrorInfo when execution throws. Shared by the synchronous tools/call path and background task-augmented executions.
ModelContextProtocol.handle_call_tool — Method
handle_call_tool(ctx::RequestContext, params::CallToolParams) -> HandlerResultHandle requests to call a specific tool with the provided parameters.
Arguments
ctx::RequestContext: The current request contextparams::CallToolParams: Parameters containing the tool name and arguments
Returns
HandlerResult: Contains either the tool execution results or an error if the tool is not found or execution fails
ModelContextProtocol.handle_cancel_task — Method
handle_cancel_task(ctx::RequestContext, params::CancelTaskParams) -> HandlerResultHandle a tasks/cancel: transition a non-terminal task to "cancelled" (waking any blocked tasks/result requests) and return the task state. Cancelling a task already in a terminal status is rejected with -32602 per spec.
ModelContextProtocol.handle_complete — Method
handle_complete(ctx::RequestContext, params::CompleteParams) -> HandlerResultHandle a completion/complete request: suggest values for a prompt argument (ref/prompt, resolved by prompt name) or a resource-template variable (ref/resource, resolved by URI template). Suggestions come from the matched component's completions sources (see completion_values); the response caps values at the spec's 100, reporting the full count as total and hasMore accordingly. An unknown ref type, prompt name, or template URI is -32602, as is a context.arguments that is not an object of strings (the schema's shape).
ModelContextProtocol.handle_get_task — Method
handle_get_task(ctx::RequestContext, params::GetTaskParams) -> HandlerResultHandle a tasks/get poll: return the task's current state, flattened into the result per the spec (GetTaskResult = Result & Task).
ModelContextProtocol.handle_initialize — Method
handle_initialize(ctx::RequestContext, params::InitializeParams) -> HandlerResultHandle MCP protocol initialization requests by setting up the server and returning capabilities.
Arguments
ctx::RequestContext: The current request contextparams::InitializeParams: The initialization parameters from the client
Returns
HandlerResult: Contains the server's capabilities and configuration
ModelContextProtocol.handle_list_prompts — Method
handle_list_prompts(ctx::RequestContext, params::ListPromptsParams) -> HandlerResultHandle requests to list available prompts on the MCP server.
Arguments
ctx::RequestContext: The current request contextparams::ListPromptsParams: Parameters for the list request (including optional cursor)
Returns
HandlerResult: Contains information about all available prompts
ModelContextProtocol.handle_list_resource_templates — Method
handle_list_resource_templates(ctx::RequestContext, params::ListResourceTemplatesParams)
-> HandlerResultHandle a resources/templates/list request: advertise the server's resource templates in the spec wire shape (resourceTemplates entries with uriTemplate, name, and optional description/mimeType/title/icons/_meta).
ModelContextProtocol.handle_list_resources — Method
handle_list_resources(ctx::RequestContext, params::ListResourcesParams) -> HandlerResultHandle requests to list all available resources on the MCP server.
Arguments
ctx::RequestContext: The current request contextparams::ListResourcesParams: Parameters for the list request (including optional cursor)
Returns
HandlerResult: Contains information about all registered resources
ModelContextProtocol.handle_list_tasks — Method
handle_list_tasks(ctx::RequestContext, params::ListTasksParams) -> HandlerResultHandle a paginated tasks/list, restricted to the requestor's authorization context. Not offered (-32601) when the server cannot identify requestors (HTTP without auth).
ModelContextProtocol.handle_list_tools — Method
handle_list_tools(ctx::RequestContext, params::ListToolsParams) -> HandlerResultHandle requests to list all available tools on the MCP server.
Arguments
ctx::RequestContext: The current request contextparams::ListToolsParams: Parameters for the list request (including optional cursor)
Returns
HandlerResult: Contains information about all registered tools
ModelContextProtocol.handle_notification — Method
handle_notification(ctx::RequestContext, notification::JSONRPCNotification) -> NothingProcess notification messages from clients that don't require responses.
Arguments
ctx::RequestContext: The current request contextnotification::JSONRPCNotification: The notification to process
Returns
Nothing: Notifications don't generate responses
ModelContextProtocol.handle_ping — Method
handle_ping(ctx::RequestContext, params::Nothing) -> HandlerResultHandle MCP protocol ping requests.
Arguments
ctx::RequestContext: The current request contextparams::Nothing: The ping parameters does not contain any data
Returns
HandlerResult: Ping returns an empty response payload
ModelContextProtocol.handle_read_resource — Method
handle_read_resource(ctx::RequestContext, params::ReadResourceParams) -> HandlerResultHandle requests to read content from a specific resource by URI.
Arguments
ctx::RequestContext: The current request contextparams::ReadResourceParams: Parameters containing the URI of the resource to read
Returns
HandlerResult: Contains either the resource contents or an error if the resource is not found or cannot be read
ModelContextProtocol.handle_request — Method
handle_request(server::Server, state::ServerState, request::Request) -> ResponseProcess an MCP protocol request and route it to the appropriate handler based on the request method.
Arguments
server::Server: The MCP server instance handling the requeststate::ServerState: The persistent server state, threaded into the request context (carries the negotiated protocol version)request::Request: The parsed JSON-RPC request to process
Behavior
This function creates a request context, then dispatches the request to the appropriate handler based on the request method. Supported methods include:
initialize: Server initializationresources/list: List available resourcesresources/read: Read a specific resourcetools/list: List available toolstools/call: Invoke a specific toolprompts/list: List available promptsprompts/get: Get a specific prompt
If an unknown method is received, a METHODNOTFOUND error is returned. Any exceptions thrown during processing are caught and converted to INTERNAL_ERROR responses.
Returns
Response: Either a successful response or an error response depending on the handler result
ModelContextProtocol.handle_set_level — Method
handle_set_level(ctx::RequestContext, params::SetLevelParams) -> HandlerResultHandle logging/setLevel requests by adjusting the installed MCPLogger's minimum level.
Accepts the MCP/RFC-5424 levels (MCP_LOG_LEVELS) and maps them to Julia LogLevels. Setting "debug" also enables the per-request lifecycle log lines emitted by handle_request. When the global logger is not an MCPLogger the request still succeeds (the preference simply has nothing to apply to).
Arguments
ctx::RequestContext: The current request contextparams::SetLevelParams: The requested minimum level
Returns
HandlerResult: Empty result on success;INVALID_PARAMSerror for unknown levels
ModelContextProtocol.handle_subscribe_resource — Method
handle_subscribe_resource(ctx::RequestContext, params::SubscribeParams) -> HandlerResultHandle resources/subscribe requests by recording the URI in the session's wire-subscription set. Returns an empty result per spec. Idempotent: repeat subscriptions to the same URI are accepted.
Arguments
ctx::RequestContext: The current request contextparams::SubscribeParams: Parameters containing the resource URI
Returns
HandlerResult: An empty result acknowledging the subscription
ModelContextProtocol.handle_task_result — Method
handle_task_result(ctx::RequestContext, params::TaskResultParams) -> HandlerResultHandle a tasks/result retrieval. For a terminal task, respond immediately with the underlying call's result or error. For a non-terminal task the spec requires blocking until terminal — the response route is detached from the (serial) server loop and a waiter task delivers the response when the task finishes, so the loop stays free to process tasks/get polls and the tasks/cancel that may be what unblocks this very request.
ModelContextProtocol.handle_unsubscribe_resource — Method
handle_unsubscribe_resource(ctx::RequestContext, params::UnsubscribeParams) -> HandlerResultHandle resources/unsubscribe requests by removing the URI from the session's wire-subscription set. Returns an empty result per spec. Idempotent: unsubscribing a URI that was never subscribed is accepted.
Arguments
ctx::RequestContext: The current request contextparams::UnsubscribeParams: Parameters containing the resource URI
Returns
HandlerResult: An empty result acknowledging the unsubscription
ModelContextProtocol.match_uri_template — Method
match_uri_template(template::String, uri::String) -> Union{Nothing,Dict{String,String}}Match uri against an RFC 6570 level-1 URI template. Each {var} placeholder matches one path segment (one or more characters excluding /). Returns the extracted variables on a full match, nothing otherwise.
Deliberate subset of RFC 6570: variable names are [A-Za-z0-9_]+ (no dotted or pct-encoded names); adjacent placeholders with no literal between them ({a}{b}) are ambiguous and never match; a repeated variable name must capture the same value in every position.
ModelContextProtocol.normalize_read_contents — Method
normalize_read_contents(data, fallback_uri::String, fallback_mime::String)
-> Vector{LittleDict{String,Any}}Normalize a resource provider's return value into spec resources/read contents entries: TextResourceContents/BlobResourceContents (or a vector of them) serialize directly — the only path that can produce binary blob contents; a String becomes the text verbatim; anything else (including custom ResourceContents subtypes) is JSON-encoded into a text entry carrying fallback_uri/fallback_mime.
ModelContextProtocol.notify_task_status — Method
notify_task_status(server::Server, record::TaskRecord) -> NothingSend an optional notifications/tasks/status with the task's full wire state. Best-effort: failures are logged at debug level and never propagate (requestors must not rely on these notifications per spec).
ModelContextProtocol.param_header_violation — Method
param_header_violation(annotated::Vector{Tuple{Vector{String},String}},
arguments, headers::Dict{String,Any})
-> Union{String,Nothing}Validate a modern-era HTTP tools/call's Mcp-Param-* headers against its body (SEP-2243 custom-header mirroring), driven by the tool's MIRROR TABLE — the (property path, suffix) pairs validate_tool_headers derived from the NORMALIZED schema at registration, so enforcement matches advertisement exactly. For every annotated path PRESENT in the request's arguments with a non-null value, the mirrored header must exist, must not be duplicated or unsafe, must decode (a =?base64?...?= sentinel is validated STRICTLY; anything else is a literal), and must match the body value — strings compare exactly, booleans through true/false, integers exactly through the full JSON number grammar, and non-integral numbers numerically.
Skipped per spec: absent paths (nothing to mirror), explicit JSON null values (clients omit the header for null, servers must not expect it), headers whose path is not in the body, and Mcp-Param-* headers matching no annotation (forward compatibility). Returns the violation description, or nothing.
ModelContextProtocol.request_protocol_version — Method
request_protocol_version(ctx::RequestContext) -> Union{String,Nothing}The protocol version in effect for THIS request: the per-request version carried in a modern-era request's _meta when present, otherwise the session version negotiated by initialize (legacy era). nothing before any negotiation.
ModelContextProtocol.serialize_resource_contents — Method
serialize_resource_contents(resource::ResourceContents) -> LittleDict{String,Any}Serialize resource contents to the spec wire shape: {uri, text, mimeType} for TextResourceContents, {uri, blob, mimeType} (base64) for BlobResourceContents.
Arguments
resource::ResourceContents: The resource contents to serialize
Returns
LittleDict{String,Any}: The serialized resource contents entry
ModelContextProtocol.spawn_task_execution! — Method
spawn_task_execution!(ctx::RequestContext, tool::MCPTool, args::AbstractDict,
record::TaskRecord) -> NothingRun a tool call in a background Julia task, recording the outcome into record and emitting a notifications/tasks/status on the terminal transition. The execution context carries the original request's progress token (valid for the task lifetime per spec) and the task record (for task_cancelled(ctx)). If the task was cancelled while running, the outcome is discarded.
ModelContextProtocol.task_principal — Method
task_principal(ctx::RequestContext) -> Union{String,Nothing}The authorization principal tasks are bound to: the authenticated subject when HTTP auth is enabled, otherwise nothing (single-user transports like stdio).
ModelContextProtocol.task_terminal_response — Method
task_terminal_response(request_id, record::TaskRecord) -> ResponseBuild the tasks/result response for a terminal task: exactly what the underlying request would have returned — its CallToolResult (with the related-task _meta added) or its JSON-RPC error. A task cancelled before completion has no underlying result, so it answers with an error. Caller must hold the store lock.
ModelContextProtocol.tasks_cancel_offered — Method
tasks_cancel_offered(server::Server) -> BoolWhether tasks/cancel is offered (a TaskCapability with cancel=true), matching what the capability advertises.
ModelContextProtocol.tasks_list_offered — Method
tasks_list_offered(server::Server) -> BoolWhether tasks/list is offered: requires a TaskCapability with list=true, and is withheld on an HTTP transport without authentication (the server cannot identify requestors there, so listing would expose task metadata across clients).
ModelContextProtocol.tasks_supported — Method
tasks_supported(ctx::RequestContext) -> BoolWhether the tasks capability is in effect for THIS session: the server is configured with a TaskCapability AND the client negotiated a protocol version with task support (2025-11-25+). When false, task metadata on requests is ignored (per spec) and the tasks/* methods do not exist.
ModelContextProtocol.validate_tool_headers — Method
validate_tool_headers(tool::MCPTool) -> Vector{Tuple{Vector{String},String}}Reject invalid SEP-2243 x-mcp-header annotations at registration and return the tool's MIRROR TABLE — the (property path, header suffix) pairs runtime enforcement uses. Rules: every annotation value must be a string, every suffix a nonempty HTTP token (it becomes part of the Mcp-Param-* header NAME), suffixes case-insensitively unique within the tool (header names are case-insensitive, so "Route" and "route" would collapse onto one mirrored header), the annotated property must declare an annotatable type (string, integer, or boolean — the spec excludes number, objects, and arrays), and annotations are only valid on statically reachable properties (never under array items, composition branches, or definitions). Advertising an invalid annotation would force conforming clients to discard the tool — better to refuse it server-side with a clear error. Throws ArgumentError on violation.
The table is derived from the NORMALIZED schema — the same JSON tree tools/list advertises — so validation, advertisement, and enforcement can never diverge (a NamedTuple-shaped raw schema serializes to ordinary JSON objects and is honored exactly as advertised).
ModelContextProtocol.with_related_task_meta — Method
with_related_task_meta(result::CallToolResult, task_id::String) -> CallToolResultReturn a copy of result whose _meta carries the spec-required io.modelcontextprotocol/related-task association for tasks/result responses.
ModelContextProtocol.LATEST_MODERN_PROTOCOL_VERSION — Constant
Latest modern-era protocol version.
ModelContextProtocol.MODERN_PROTOCOL_VERSIONS — Constant
Modern-era (stateless, per-request _meta) MCP protocol versions supported by this implementation, newest first. A request carrying io.modelcontextprotocol/protocolVersion in _meta is served statelessly under one of these versions; initialize selects legacy semantics from SUPPORTED_PROTOCOL_VERSIONS. Both eras are served concurrently (dual-era server, per the 2026-07-28 spec's backward-compatibility model).
ModelContextProtocol.MODERN_CACHEABLE_METHODS — Constant
Modern methods whose complete results are CacheableResults: the spec REQUIRES ttlMs and cacheScope on them.
ModelContextProtocol.MODERN_METHODS — Constant
Methods served in the modern era, each gated on the capability that provides it (nothing = always available). Methods REMOVED from the modern era — ping, logging/setLevel, resources/subscribe/unsubscribe (replaced by subscriptions/listen), and the legacy core tasks methods tasks/result and tasks/list — return METHODNOTFOUND on modern requests even though the legacy era serves them. tasks/get, tasks/update, and tasks/cancel belong to the io.modelcontextprotocol/tasks EXTENSION (SEP-2663): always dispatchable, but gated in-handler on the request's declared extension capability (-32021 for non-declaring clients, per the extension's error rules — not -32601). A method whose capability the server does not declare is equally METHODNOTFOUND: the advertised capability set and the callable surface must agree.
ModelContextProtocol.dispatch_modern — Method
dispatch_modern(ctx::RequestContext, request::Request) -> HandlerResultRoute a validated modern-era request to its handler. Shared feature handlers (tools, resources, prompts) are reused from the legacy era; server/discover is modern-only. Requests whose typed params failed to parse get -32602 rather than an internal error.
Arguments
ctx::RequestContext: The request context (carries the per-request protocol version)request::Request: The parsed request
Returns
HandlerResult: The handler's result
ModelContextProtocol.handle_discover — Method
handle_discover(ctx::RequestContext) -> HandlerResultHandle server/discover (a server MUST in the modern era): advertise the protocol versions this server supports across both eras, its modern capability surface, and optional instructions, with the CacheableResult fields (ttlMs, cacheScope) the spec requires on discovery results. resultType and serverInfo are attached by the modern envelope.
Capabilities carry only what the modern era actually serves: the features present, their listChanged/subscribe flags (delivered via subscriptions/listen), logging when declared (per-request logLevel opt-in — a MUST for servers that emit notifications/message), and no legacy-only tasks — and never the legacy builder's embedded resource listings, which would leak resource metadata into shared caches and do not match the modern ServerCapabilities shape.
Arguments
ctx::RequestContext: The current request context
Returns
HandlerResult: The discovery result
ModelContextProtocol.handle_modern_request — Method
handle_modern_request(server::Server, state::ServerState, request::Request;
authenticated_user=nothing) -> Union{Response,Nothing}Serve a modern-era (2026-07-28+) request statelessly: validate the per-request _meta protocol fields, dispatch to the shared feature handlers, and apply the modern result envelope plus the CacheableResult fields where required. The handler context gets a FRESH ServerState — modern requests are self-contained, and a ctx-aware tool handler must not be able to mutate the legacy session's state.
Validation, in order (per the spec):
- missing
protocolVersion(only reachable forserver/discover, which routes modern unconditionally) → -32602 Invalid params - unsupported
protocolVersion→UnsupportedProtocolVersionError(-32022) withdata.supported/data.requested - missing
clientCapabilities→ -32602 Invalid params (a required_metafield) - present but unrecognized
logLevel→ -32602 Invalid params (the spec's SHOULD; presence-aware — a mistyped value is rejected, never treated as absent) - method not on the modern surface (or its capability undeclared) → -32601
notifications/message follows the per-request opt-in: a request that set a valid io.modelcontextprotocol/logLevel (and passed all validation) gets records at or above that level on its own response stream, provided the server declares the logging capability; every other modern request gets none — the suppression flag the loop armed stays set through the iteration, covering the loop's own post-dispatch lifecycle records too. subscriptions/listen never honors the opt-in: its response stream IS the subscription stream, and the spec forbids notifications/message there.
Arguments
server::Server: The MCP server instancestate::ServerState: The legacy session state (NOT given to handlers; see above)request::Request: The parsed request (withmeta.protocol_versionset)authenticated_user: Per-request identity from HTTP auth, elsenothing
Returns
Union{Response,Nothing}: The response to send
ModelContextProtocol.modern_cache_scope — Method
modern_cache_scope(server::Server) -> StringThe cacheScope for this server's cacheable results: "private" when bearer auth is enabled (responses are served inside an authorization context and MUST NOT be shared across contexts by intermediaries), "public" otherwise.
Arguments
server::Server: The server instance
Returns
String:"public"or"private"
ModelContextProtocol.modern_input_required_response — Method
modern_input_required_response(server::Server, ir::InputRequired, id,
method::String, client_capabilities,
params_digest, principal::String) -> ResponseBuild the modern-era response for a handler's InputRequired (MRTR): the -32021 MissingRequiredClientCapability error when the request did not declare a capability the input requests need, otherwise the enveloped InputRequiredResult (resultType input_required + inputRequests + a minted requestState). Shared by the in-loop serve path and off-loop detachable tool calls (tasks extension), so both build byte-identical responses.
Arguments
server::Server: The MCP server instanceir::InputRequired: The handler's input-required valueid: The request id to respond withmethod::String: The request method (bound into the requestState)client_capabilities: The request's declared_metaclient capabilitiesparams_digest: The request's canonical params digestprincipal::String: The MRTR principal (seemrtr_principal)
Returns
Response: The error or enveloped result response
ModelContextProtocol.modern_invalid_params — Method
modern_invalid_params(ctx::RequestContext, method::String) -> HandlerResultBuild the -32602 Invalid params result for a modern request whose typed parameters are missing or malformed.
ModelContextProtocol.modern_method_available — Method
modern_method_available(server::Server, method::String) -> BoolWhether method exists on this server's modern surface: it must be a modern-era method AND its providing capability must be declared — the advertised capability set and the callable surface must agree.
Arguments
server::Server: The server instancemethod::String: The request method
Returns
Bool: true when the method is callable in the modern era
ModelContextProtocol.modern_result_envelope — Method
modern_result_envelope(response::JSONRPCResponse, server::Server) -> JSONRPCResponseApply the modern-era result envelope: every result MUST carry resultType ("complete" unless the handler set one) and SHOULD identify the server via io.modelcontextprotocol/serverInfo in the result's _meta (merged into any handler-provided _meta).
The known handler result types are re-shaped WITHOUT a JSON round-trip, so values travel by reference — no numeric precision loss (Int64 above 2^53 survives) and no extra copies of base64 payloads. Only unknown result types fall back to an untyped JSON3 round-trip (which preserves Int64, unlike a Dict{String,Any}-typed read).
Arguments
response::JSONRPCResponse: The handler's responseserver::Server: The server (forserverInfo)
Returns
JSONRPCResponse: A response whose result carries the modern envelope fields
ModelContextProtocol.modernize_error_code — Method
modernize_error_code(code::Int) -> IntMap legacy-range error codes to their modern-era replacements. The 2026-07-28 allocation policy grandfathers -32000..-32019 for legacy responses but modern responses must use spec codes: not-found conditions for resources (-32000), tools (-32001), URIs (-32002, reserved — MUST NOT be emitted), and prompts (-32003) are all -32602 Invalid params in the modern era.
Arguments
code::Int: A legacy-era error code
Returns
Int: The code to emit on a modern-era response
ModelContextProtocol.serve_modern — Method
serve_modern(server::Server, request::Request, version::String, mrtr_state,
authenticated_user) -> Union{Response,Nothing}Dispatch a fully validated modern-era request and build its response (envelope, CacheableResult fields, MRTR inputrequired handling). Split out of `handlemodern_request` so the per-request log opt-in can re-scope the logger around the whole serve path.
Arguments
server::Server: The MCP server instancerequest::Request: The validated requestversion::String: The request's protocol versionmrtr_state: The verified MRTR state payload, ornothingauthenticated_user: Per-request identity from HTTP auth, elsenothing
Returns
Union{Response,Nothing}: The response to send (nothingwhen deferred)
ModelContextProtocol.InputRequest — Type
InputRequest(method::String, params)One entry of an InputRequiredResult's inputRequests map: a request the client should fulfill and answer in its retry's inputResponses. Only the three spec-blessed request types are valid — construct via elicit_request, sampling_request, or roots_request.
Fields
method::String: The request method (elicitation/create,sampling/createMessage,roots/list)params::Any: The request's params (a Dict, ornothingfor none)
ModelContextProtocol.canonical_json_digest — Method
canonical_json_digest(x) -> StringSHA-256 hex digest of the canonical (sorted-key) JSON serialization of x. Used to bind an issued requestState to the exact original params it may resume.
Arguments
x: Any parsed JSON value
Returns
String: The hex digest
ModelContextProtocol.canonicalize_json — Method
canonicalize_json(x) -> AnyRebuild a JSON value with all object keys sorted (recursively), producing a serialization-stable structure for digesting. Non-container values pass through.
Arguments
x: Any parsed JSON value
Returns
- The canonical structure
ModelContextProtocol.capability_satisfied — Method
capability_satisfied(client_capabilities, r::InputRequest) -> BoolWhether this request's declared _meta client capabilities cover input request r. Declaration means the capability VALUE is an object (a null or scalar value declares nothing — including MODE values: {"elicitation": {"form": null}} declares no form support), and subfeatures are honored:
- form-mode elicitation:
formdeclared with an object value covers it, and ONLY the bare emptyelicitationobject implies it — any other declared mode set (url, or modes from a future revision) excludes form - tool-enabled sampling (
params.toolsORparams.toolChoicepresent): requiressampling.toolsdeclared as an object, not justsampling
Arguments
client_capabilities: The request's declared client capabilities (any JSON value)r::InputRequest: The input request to check
Returns
Bool: true whenrmay be sent to this client
ModelContextProtocol.input_required_envelope — Method
input_required_envelope(server::Server, ir::InputRequired, method::String,
params_digest, principal::String) -> LittleDict{String,Any}Build the InputRequiredResult wire shape for a handler's InputRequired value: resultType: "input_required", the inputRequests map (each entry {method, params?}), and a freshly minted requestState bound to this method, principal, and params digest. Capability checking is the caller's job (undeclared_capability_requirements) — it must reject with -32021 BEFORE building this envelope.
Arguments
server::Server: The serverir::InputRequired: The handler's valuemethod::String: The request method (bound into the state token)params_digest: The request's canonical params digestprincipal::String: The requesting principal
Returns
LittleDict{String,Any}: The result object
ModelContextProtocol.issue_request_state — Method
issue_request_state(server::Server, method::String, params_digest,
principal::String, handler_state) -> StringMint an integrity-protected requestState token: an HMAC-SHA256-signed payload embedding issue time + TTL, the principal, the ORIGINATING METHOD, the canonical digest of the original request params, and the handler's carried state. Signed with the per-server key, so a token survives neither tampering nor (with the default ephemeral key) a server restart. Binding the method prevents cross-method state confusion: tools/call and prompts/get params can be structurally identical, and a token issued for one must not resume the other.
Arguments
server::Server: The server (holds the signing key)method::String: The request method the state was issued forparams_digest: The request's canonical params digest (fromRequestMeta)principal::String: The requesting principal (mrtr_principal)handler_state: The handler's JSON-serializable state (may benothing)
Returns
String: The token (base64(payload).base64(mac))
ModelContextProtocol.mrtr_principal — Method
mrtr_principal(user::Union{AuthenticatedUser,Nothing}) -> StringThe principal string bound into a requestState: the canonical provider-qualified identity (see principal_identity), or "" when the request is unauthenticated. A state issued to one principal must not be redeemable by another — including a DIFFERENT provider's token that happens to carry the same subject.
Arguments
user::Union{AuthenticatedUser,Nothing}: The request's authenticated user
Returns
String: The principal
ModelContextProtocol.principal_identity — Method
principal_identity(user::AuthenticatedUser) -> StringThe canonical, collision-free identity string for an authenticated principal: the JSON array [provider, subject]. Two identity providers can issue the same sub, so the subject alone must never identify a principal; JSON encoding (not delimiter concatenation) makes the pair unambiguous — ("a", "b\x1fc") and ("a\x1fb", "c") cannot collide. username is display-oriented and mutable, so it never participates.
ModelContextProtocol.undeclared_capability_requirements — Method
undeclared_capability_requirements(ir::InputRequired, client_capabilities)
-> LittleDict{String,Any}The requiredCapabilities object for the capabilities ir's input requests need but this request did not declare — a ClientCapabilities-shaped object precise to the subfeature: {"elicitation": {"form": {}}} for a form elicitation, {"sampling": {}} for plain sampling, {"sampling": {"tools": {}}} for tool-enabled sampling. A server MUST NOT send inputRequests the client did not declare support for: a non-empty return means the request must be rejected with -32021 carrying this object as error.data.requiredCapabilities.
Arguments
ir::InputRequired: The handler's input-required valueclient_capabilities: The request's declared client capabilities (any JSON value)
Returns
LittleDict{String,Any}: The missing requirements (empty when all declared)
ModelContextProtocol.verify_request_state — Method
verify_request_state(server::Server, token::AbstractString, method::String,
params_digest, principal::String) -> Tuple{Bool,Any}Verify a retry's requestState BEFORE any handler runs: signature (constant-time), TTL, principal, originating method, and original-params digest must all hold — the token is attacker-controlled input. Returns (true, handler_state) on success or (false, reason) on any failure.
Arguments
server::Server: The server (holds the signing key)token::AbstractString: The offeredrequestStatemethod::String: THIS request's method (must equal the issuing method)params_digest: THIS request's canonical params digest (must equal the original's)principal::String: THIS request's principal
Returns
Tuple{Bool,Any}:(ok, handler_state_or_reason)
ModelContextProtocol.call_tool_result_wire — Method
call_tool_result_wire(result::CallToolResult) -> LittleDict{String,Any}Serialize a CallToolResult to the plain result object inlined on a completed task (tasks/get result field): content/isError plus structuredContent and _meta when present. No resultType (it is a nested result, not a response envelope) and no legacy related-task _meta (the taskId is already at the response root, and SEP-2663 forbids the redundant key).
ModelContextProtocol.ensure_task_notifications! — Method
ensure_task_notifications!(server::Server) -> Nothing(Re)install the notifications/tasks dispatch pipeline when it is absent or its queue has been closed — stop! and the server-loop shutdown both close the queue (ending the dispatcher so it cannot pin the server past its lifetime), so a server started again needs a fresh queue and dispatcher. A live pipeline is left untouched.
ModelContextProtocol.ext_task_authorized — Method
ext_task_authorized(ctx::RequestContext, record::TaskRecord) -> BoolRe-authorize a task-related request against the task's recorded requirements (SEP-2663: authorization checks on EVERY task request, not only at creation): when the request is authenticated, the current token must carry every scope the originating tool required. A failure is reported as task-not-found by the caller, indistinguishable from an unknown id.
ModelContextProtocol.ext_task_principal — Method
ext_task_principal(ctx::RequestContext) -> Union{String,Nothing}The authorization principal extension tasks are bound to. Unlike the legacy task_principal (subject only), this binds provider AND subject via the canonical collision-free principal_identity — two identity providers can issue the same sub, and a token from the wrong provider must not resolve another caller's task. nothing when auth is not enabled (single-user transports). Shares its encoding with the MRTR requestState principal, so the composition flow (MRTR round, then task creation) is bound to one identity end-to-end.
ModelContextProtocol.ext_task_wire — Method
ext_task_wire(record::TaskRecord; detailed::Bool=false) -> LittleDict{String,Any}Serialize a task record to the SEP-2663 wire shape: taskId, status, optional statusMessage, createdAt/lastUpdatedAt (ISO 8601 UTC), ttlMs (always present; null = unlimited), and pollIntervalMs — integer milliseconds, and never the legacy ttl/pollInterval keys. With detailed=true the status-specific DetailedTask payload is inlined: result for "completed", error for "failed", inputRequests for "input_required". Caller must hold the store lock.
ModelContextProtocol.handle_ext_cancel_task — Method
handle_ext_cancel_task(ctx::RequestContext, params::CancelTaskParams) -> HandlerResultHandle a modern-era tasks/cancel (tasks extension): signal cancellation intent and acknowledge with an empty result. Cancellation is cooperative and eventually consistent — a running handler observes it via task_cancelled(ctx), and the ack is idempotent: cancelling an already-terminal task acks identically (-32602 is reserved for unknown taskIds, a deliberate delta from the legacy era's terminal-cancel rejection). Gated on the extension declaration (-32021).
ModelContextProtocol.handle_ext_get_task — Method
handle_ext_get_task(ctx::RequestContext, params::GetTaskParams) -> HandlerResultHandle a modern-era tasks/get poll (tasks extension): return the DetailedTask for the task's current status, with the terminal result/error inlined. Gated on the extension declaration (-32021); an unknown, expired, cross-principal, or legacy-era taskId is -32602.
ModelContextProtocol.handle_ext_update_task — Method
handle_ext_update_task(ctx::RequestContext, params::UpdateTaskParams) -> HandlerResultHandle a modern-era tasks/update (tasks extension): deliver the client's inputResponses to the task's outstanding input requests, acknowledging with an empty result. Responses keyed to requests that are not currently outstanding — never issued, already answered, or superseded — are ignored per spec, and a partial set (a strict subset of the outstanding keys) is accepted: answered keys are removed and the task stays input_required until the rest arrive; once nothing is pending the status returns to working. The ack is eventually consistent — delivery happens before the ack here, but the resumed handler runs concurrently, so the observable status is whatever tasks/get sees next. Gated on the extension declaration (-32021); an unknown taskId is -32602.
ModelContextProtocol.install_task_notifications! — Method
install_task_notifications!(server::Server) -> NothingWire the tasks extension's notifications/tasks status updates: install the store's status-change hook so every extension-era transition (parking on input, resuming, completing, failing, cancelling, expiring) pushes the task's complete DetailedTask — identical to what tasks/get would return at that moment — to the subscriptions/listen streams that subscribed to the task's id.
The hook runs under the store lock (which the wire snapshot requires) but does NO transport I/O there: it enqueues the snapshot — plus the task's transition-time principal and required_scopes, re-checked per stream at delivery — onto a bounded FIFO consumed by a single dispatcher task, which broadcasts OUTSIDE the store lock. A stalled client can therefore never wedge the task store (a synchronous stdio write under the lock would block every tasks/* request once the client's pipe fills), the single consumer preserves transition order, and a full queue load-sheds (best-effort pushes; polling stays authoritative). Installed by mcp_server; stop! closes the queue, ending the dispatcher.
ModelContextProtocol.safe_error_message — Method
safe_error_message(prefix::String, e) -> StringFormat an exception for an error message WITHOUT trusting its show/showerror methods: an exception whose display itself throws must not escape the error path it is being reported on (it would defeat every catch that interpolates $(e) and, on the task-worker path, leave a delivered task non-terminal forever). Falls back to the exception's type name, then to a static string.
ModelContextProtocol.spawn_detachable_tool_call! — Method
spawn_detachable_tool_call!(ctx::RequestContext, tool::MCPTool,
args::AbstractDict,
tool_scopes::Vector{String}) -> HandlerResultRun a task-capable modern-era tools/call off the serial server loop: capture the request's response route, spawn the handler on a background Julia task, and defer. tool_scopes is the caller's snapshot of the tool's required_scopes — the exact set this request was authorized against, recorded onto a minted task for per-request re-authorization. The handler decides the response shape by what it does first:
- returns without detaching → ordinary synchronous result (the immediate-result shortcut), delivered on the captured route
- returns
InputRequiredwithout detaching → the MRTR round (capability check,input_requiredenvelope) — this is what lets MRTR exchanges resolve BEFORE task creation, per the SEP-2663 composition rule - calls
task_detach(ctx)→ theCreateTaskResultwas already delivered; the eventual outcome is recorded into the task (aCallToolResultcompletes it, a thrown error fails it with the JSON-RPC error inlined)
The worker guarantees exactly one outcome on every path: any throw between the handler's return and the response delivery — including one raised by a diagnostic logger — lands in a last-resort catch that answers -32603 (or fails the already-created task).
ModelContextProtocol.tasks_extension_declared — Method
tasks_extension_declared(client_capabilities) -> BoolWhether this request declared the io.modelcontextprotocol/tasks extension in its _meta clientCapabilities. Declaration means the extension key is present under extensions with an OBJECT value (the spec's "an empty object indicates support"; a null or scalar value declares nothing, matching the MRTR capability rules).
ModelContextProtocol.tasks_extension_required_error — Method
tasks_extension_required_error() -> ErrorInfoThe -32021 MissingRequiredClientCapability error for task-surface requests from a client that did not declare the tasks extension, carrying the spec's requiredCapabilities object naming the extension.
ModelContextProtocol.broadcast_subscription_notification — Method
broadcast_subscription_notification(server::Server, method::String;
params::AbstractDict=LittleDict{String,Any}(),
uri::Union{String,Nothing}=nothing,
task_id::Union{String,Nothing}=nothing) -> IntDeliver a notification to every subscriptions/listen stream that opted into it, tagged with each stream's own subscription id. Every record — not just the filter matches — is swept for liveness (route_alive), so a disconnected client whose filter never matches anything still gets pruned. Returns the number of streams the notification reached.
Delivery happens while holding the registry lock (every delivery path enqueues without blocking), so a broadcast cannot interleave with a stream's registration or graceful closure; see the SubscriptionRegistry docstring for the lock ordering.
Arguments
server::Server: The server whose subscriptions to notifymethod::String: The notification methodparams::AbstractDict: Additional notification paramsuri::Union{String,Nothing}: Fornotifications/resources/updated, the resource URItask_id::Union{String,Nothing}: Fornotifications/tasks, the task idauthorize: Optional per-stream predicaterecord::SubscriptionRecord -> Boolchecked after the filter match — used bynotifications/tasksto re-authorize each delivery against the stream's stored principal/scopes WITHOUT taking the task-store lock here (the ordering store → registry must never reverse)
Returns
Int: How many streams received the notification
ModelContextProtocol.cancel_subscription! — Method
cancel_subscription!(server::Server, request_id) -> BoolCancel an active subscriptions/listen stream by its originating request id — the notifications/cancelled path, which is how a stdio client (which cannot close a response stream) ends a subscription. The record is removed so no further messages carry its id; per JSON-RPC cancellation semantics no response is sent.
Only ROUTELESS records (stream transports like stdio, where the single shared channel means the cancellation can only come from the stream's own client) are cancellable this way. A route-bound (HTTP) stream is cancelled by closing the response stream itself — an in-band cancellation message must never be honored for it, because on HTTP the notification can arrive on ANY connection: honoring it would let one client end another client's stream by guessing its id.
Arguments
server::Server: The server holding the subscriptionrequest_id: The listen request's JSON-RPC id (from the notification'srequestId)
Returns
Bool: true when an active subscription was cancelled
ModelContextProtocol.close_subscriptions! — Method
close_subscriptions!(server::Server) -> NothingEnd all subscriptions/listen streams gracefully: each open stream receives the JSON-RPC response to its originating listen request (an empty complete result tagged with its subscription id and carrying serverInfo like every other modern result), which is how a client distinguishes an orderly server shutdown from an abrupt transport drop. Called during server shutdown.
The closing results are delivered while holding the registry lock, so a concurrent broadcast can never write on a stream AFTER its graceful result: the broadcast either completes first or finds an empty registry.
Arguments
server::Server: The server whose subscriptions to close
Returns
Nothing
ModelContextProtocol.handle_subscriptions_listen — Method
handle_subscriptions_listen(ctx::RequestContext, params::SubscriptionsListenParams) -> HandlerResultOpen a subscriptions/listen stream: validate the filter (a malformed one is rejected with -32602, not silently emptied), send notifications/subscriptions/acknowledged as the stream's FIRST message (carrying the honored subset of the requested filter), register the subscription, and defer the request's response — the stream stays open until the client closes it, cancels it (notifications/cancelled on stdio), or the server shuts down (close_subscriptions!).
Ack-then-register happens under the registry lock, so a concurrent broadcast can neither enqueue a change notification ahead of the acknowledgment nor observe a half-registered stream — and a stream whose ack cannot be delivered is never registered at all.
Notification types the server cannot deliver are omitted from the acknowledged filter rather than silently accepted, so a client can tell what it will actually receive.
Arguments
ctx::RequestContext: The current request contextparams::SubscriptionsListenParams: The request's notification filter
Returns
HandlerResult: A deferred result (the response, if any, arrives at closure)
ModelContextProtocol.legacy_session_notification — Method
legacy_session_notification(state::ServerState, transport, method::String;
params::AbstractDict = LittleDict{String,Any}()) -> BoolDeliver a plain JSON-RPC notification to the connected legacy session, if there is one. The caller passes the session state and transport it already fetched (one snapshot per announcement — a concurrent restart cannot authorize against one session and deliver through another). The session must have completed a real initialize handshake: initialized alone is not proof (a bare notifications/initialized sets it), so a negotiated protocol_version is required too — a server that only ever served modern requests is never armed for legacy delivery.
Delivery is transport-polymorphic via send_notification — stdout on stdio, the standalone GET SSE stream on Streamable HTTP. The ambient request route is explicitly bypassed for the send: when an announcement happens inside a request handler (legacy or modern), the legacy notification must go out-of-band to the legacy session's own stream, never onto the calling request's response channel (which on a modern request would leak it to a different — possibly differently authenticated — client).
Arguments
state::ServerState: The legacy session state snapshottransport: The transport snapshot (Transportornothing)method::String: The notification methodparams::AbstractDict: The notification's params
Returns
Bool:truewhen the transport handoff was attempted without error — NOT proof of enqueue or client receipt (a disconnected HTTP transport, or one whose notification queue is at its soft cap, drops silently);falsewhen there is no handshaken legacy session, no transport, or the send threw
ModelContextProtocol.list_changed_declared — Method
list_changed_declared(server::Server, kind::Symbol) -> BoolReport whether the server declares the listChanged capability for kind — the gate for sending notifications/{kind}/list_changed to the legacy session (modern subscriptions/listen streams are gated per-stream at ack time instead, via the honored filter subset).
Arguments
server::Server: The server whose declared capabilities to checkkind::Symbol: One of:tools,:prompts,:resources
Returns
Bool: Whether the matching capability declareslist_changed = true
ModelContextProtocol.subscription_notification — Method
subscription_notification(method::String, params::AbstractDict, sub_id) -> StringSerialize a notification for delivery on a subscriptions/listen stream, tagging it with the subscription id the spec requires on every stream message.
Arguments
method::String: The notification methodparams::AbstractDict: The notification's params (the_metatag is added here)sub_id: The subscription id (the listen request's JSON-RPC id)
Returns
String: The serialized JSON-RPC notification
Core Implementation
ModelContextProtocol.process_message — Method
process_message(server::Server, state::ServerState, message::String) -> Union{String,Nothing}Process an incoming JSON-RPC message and generate an appropriate response.
Arguments
server::Server: The MCP server instancestate::ServerState: Current server statemessage::String: Raw JSON-RPC message to process
Returns
Union{String,Nothing}: A serialized response string or nothing for notifications
ModelContextProtocol.run_server_loop — Method
run_server_loop(server::Server, state::ServerState) -> NothingExecute the main server loop that reads JSON-RPC messages from the transport and writes responses back. Implements optimized CPU usage by blocking on input rather than active polling.
Arguments
server::Server: The MCP server instance with configured transportstate::ServerState: The server state object to track running status
Returns
Nothing: The function runs until interrupted or state.running becomes false
ModelContextProtocol.CapabilityResponse — Type
CapabilityResponse(;
listChanged::Bool=false,
subscribe::Union{Bool,Nothing}=nothing,
tools::Union{Dict{String,Any},Nothing}=nothing,
resources::Union{Vector{Dict{String,Any}},Nothing}=nothing)Define response structure for capabilities including tool and resource listings.
Fields
listChanged::Bool: Whether listings can change during server lifetime.subscribe::Union{Bool,Nothing}: Whether subscriptions are supported.tools::Union{Dict{String,Any},Nothing}: Tool definitions by name.resources::Union{Vector{Dict{String,Any}},Nothing}: Available resource listings.
ModelContextProtocol.CompletionCapability — Type
CompletionCapability()Advertise argument-completion support (completion/complete): contextual value suggestions for prompt arguments and resource-template variables, declared as the completions capability. Sources are configured per component via the completions field on MCPPrompt / ResourceTemplate; components without sources serve empty suggestion lists.
ModelContextProtocol.LoggingCapability — Type
LoggingCapability(; levels::Vector{String}=["info", "warn", "error"])Configure logging-related capabilities for an MCP server.
Fields
levels::Vector{String}: Supported logging levels.
ModelContextProtocol.PromptCapability — Type
PromptCapability(; list_changed::Bool=false)Configure prompt-related capabilities for an MCP server.
Fields
list_changed::Bool: Whether server supports notifications when prompt listings change.
ModelContextProtocol.ResourceCapability — Type
ResourceCapability(; list_changed::Bool=false, subscribe::Bool=false)Configure resource-related capabilities for an MCP server.
Fields
list_changed::Bool: Whether server supports notifications when resource listings change.subscribe::Bool: Whether server supports subscriptions to resource updates.
ModelContextProtocol.TaskCapability — Type
TaskCapability(; list::Bool=true, cancel::Bool=true)Configure MCP Tasks support (SEP-1686, experimental): task-augmented tools/call plus the tasks/get, tasks/result, and optionally tasks/list/tasks/cancel operations. Only advertised to clients that negotiated protocol 2025-11-25 or later.
Fields
list::Bool: Whethertasks/listis offered. Note: on an HTTP transport without authentication the server cannot identify requestors, solistis withheld from the advertised capability regardless of this setting (per the spec's security guidance).cancel::Bool: Whethertasks/cancelis offered.
ModelContextProtocol.ToolCapability — Type
ToolCapability(; list_changed::Bool=false)Configure tool-related capabilities for an MCP server.
Fields
list_changed::Bool: Whether server supports notifications when tool listings change.
ModelContextProtocol.capabilities_to_protocol — Method
capabilities_to_protocol(capabilities::Vector{Capability}, server::Server) -> Dict{String,Any}Convert server capabilities to the initialization response format required by the MCP protocol.
Arguments
capabilities::Vector{Capability}: List of server capabilities.server::Server: The server containing tools and resources.
Returns
Dict{String,Any}: Protocol-formatted capabilities dictionary including available tools and resources.
ModelContextProtocol.create_init_response — Method
create_init_response(server::Server, protocol_version::String) -> InitializeResultCreate the initialization response for an MCP server.
Arguments
server::Server: The server to create the response for.protocol_version::String: MCP protocol version string.
Returns
InitializeResult: Initialization response including server capabilities and info.
ModelContextProtocol.merge_capabilities — Method
merge_capabilities(base::Vector{Capability}, override::Vector{Capability}) -> Vector{Capability}Merge two sets of capabilities, with the override set taking precedence.
Arguments
base::Vector{Capability}: Base set of capabilities.override::Vector{Capability}: Override capabilities that take precedence.
Returns
Vector{Capability}: Merged set of capabilities.
ModelContextProtocol.to_protocol_format — Method
to_protocol_format(cap::Capability) -> Dict{String,Any}Convert an MCP capability to the JSON format expected by the MCP protocol.
Arguments
cap::Capability: The capability to convert.
Returns
Dict{String,Any}: Protocol-formatted capability dictionary.
ModelContextProtocol.auto_register! — Method
auto_register!(server::Server, dir::AbstractString) -> ServerAutomatically register MCP components found in the specified directory structure.
Arguments
server::Server: The server to register components withdir::AbstractString: Root directory containing component subdirectories
Directory Structure
dir/tools/: Contains tool definition filesdir/resources/: Contains resource definition filesdir/prompts/: Contains prompt definition files
Each subdirectory is optional. Files should be .jl files containing component definitions.
Component File Format
Component files must have the tool/resource/prompt as the last expression in the file. The return value of include() is used to obtain the component.
Example:
# tools/my_tool.jl
julia_version_tool = MCPTool(
name = "julia_version",
description = "Get Julia version",
handler = params -> Dict("version" => string(VERSION))
) # ← This must be the last expressionReturns
Server: The updated server instance for method chaining
ModelContextProtocol.default_capabilities — Method
default_capabilities() -> Vector{Capability}Create the default set of server capabilities for an MCP server.
Returns
Vector{Capability}: Default capabilities including resources, tools, and prompts
ModelContextProtocol.normalize_path — Method
normalize_path(path::String) -> StringConvert paths to absolute form, resolving relative paths against the project root.
Arguments
path::String: The path to normalize
Returns
String: Absolute, normalized path with all symbolic links resolved
ModelContextProtocol.scan_mcp_components — Method
scan_mcp_components(dir::String) -> Dict{Symbol,Vector}Scan a directory recursively for MCP component definitions (tools, resources, prompts).
Arguments
dir::String: Directory path to scan for component definitions
Returns
Dict{Symbol,Vector}: Dictionary of found components grouped by type
ModelContextProtocol.ProgressToken — Type
ProgressTokenType alias for tokens used to track long-running operations.
Type
Union{String,Int} - Can be either a string or integer identifier
ModelContextProtocol.RequestId — Type
RequestIdType alias for JSON-RPC request identifiers.
Type
Union{String,Int} - Can be either a string or integer identifier
ModelContextProtocol.Capability — Type
CapabilityAbstract base type for all MCP protocol capabilities. Capabilities represent protocol features that servers can support. Concrete implementations define configuration for specific feature sets.
ModelContextProtocol.MCPMessage — Type
MCPMessageAbstract base type for all message types in the MCP protocol. Serves as the root type for requests, responses, and notifications.
ModelContextProtocol.Notification — Type
Notification <: MCPMessageAbstract base type for one-way notifications in the MCP protocol. Notification messages don't expect a corresponding response.
ModelContextProtocol.Progress — Type
Progress(; token::Union{String,Int}, current::Float64,
total::Union{Float64,Nothing}=nothing, message::Union{String,Nothing}=nothing)Track progress of long-running operations in the MCP protocol.
Fields
token::Union{String,Int}: Unique identifier for the progress trackercurrent::Float64: Current progress valuetotal::Union{Float64,Nothing}: Optional total expected valuemessage::Union{String,Nothing}: Optional status message
ModelContextProtocol.Request — Type
Request <: MCPMessageAbstract base type for client-to-server requests in the MCP protocol. Request messages expect a corresponding response from the server.
ModelContextProtocol.RequestParams — Type
RequestParamsAbstract base type for all parameter structures in MCP protocol requests. Concrete subtypes define parameters for specific request methods.
ModelContextProtocol.Resource — Type
ResourceAbstract base type for all MCP resources. Resources represent data that can be read by clients.
ModelContextProtocol.Response — Type
Response <: MCPMessageAbstract base type for server-to-client responses in the MCP protocol. Response messages are sent from the server in reply to client requests.
ModelContextProtocol.ResponseResult — Type
ResponseResultAbstract base type for all result structures in MCP protocol responses. Concrete subtypes define result formats for specific response methods.
ModelContextProtocol.Role — Type
RoleEnum representing roles in the MCP protocol.
Values
user: Content or messages from the userassistant: Content or messages from the assistant
ModelContextProtocol.ServerConfig — Type
ServerConfig(; name::String, version::String="1.0.0",
description::String="", capabilities::Vector{Capability}=Capability[],
instructions::String="",
title::Union{String,Nothing}=nothing,
icons::Union{Vector{MCPIcon},Nothing}=nothing)Define configuration settings for an MCP server instance.
Fields
name::String: The server name shown to clientsversion::String: Server implementation version (e.g., "1.0.0", "2.3.1") - YOUR server's version, not the protocol versiondescription::String: Human-readable server descriptioncapabilities::Vector{Capability}: Protocol capabilities supported by the serverinstructions::String: Usage instructions for clientstitle::Union{String,Nothing}: Optional human-friendly display nameicons::Union{Vector{MCPIcon},Nothing}: Optional icons for UI display
ModelContextProtocol.ServerError — Type
ServerError(message::String) <: ExceptionException type for MCP server-specific errors.
Fields
message::String: The error message describing what went wrong
ModelContextProtocol.ServerState — Type
ServerState()Track the internal state of an MCP server during operation.
Fields
initialized::Bool: Whether the server has been initialized by a clientrunning::Bool: Whether the server main loop is activelast_request_id::Int: Last used request ID for server-initiated requestspending_requests::Dict{RequestId,String}: Map of request IDs to method namesprotocol_version::Union{String,Nothing}: MCP protocol version negotiated during initialization (seenegotiate_version), ornothingbefore the client initializes. Server-global, not data-raced: all handler execution is serialized throughrun_server_loop. As withsession_id, the transport is single-session, so a repeatinitializeoverwrites this ("last initialize wins")wire_subscriptions::Set{String}: Resource URIs the client subscribed to viaresources/subscribe
ModelContextProtocol.Subscription — Type
Subscription(; uri::String, callback::Function, created_at::DateTime=now())Define a subscription to resource updates in the MCP protocol.
Fields
uri::String: The URI of the subscribed resourcecallback::Function: Function to call when the resource is updatedcreated_at::DateTime: When the subscription was created
ModelContextProtocol.Tool — Type
ToolAbstract base type for all MCP tools. Tools represent operations that can be invoked by clients.
Base.convert — Method
convert(::Type{URI}, s::String) -> URIConvert a string to a URI object.
Arguments
s::String: The string to convert
Returns
URI: The resulting URI object
ModelContextProtocol.icon_to_dict — Method
icon_to_dict(icon::MCPIcon) -> LittleDict{String,Any}Serialize an MCPIcon to a dictionary, omitting nothing fields.
ModelContextProtocol.PendingTaskInput — Type
PendingTaskInput(method::String, params, channel::Channel{Any})One outstanding mid-task input request on an extension-era task (SEP-2663): the request the client sees under the task's inputRequests (as {method, params?} on tasks/get), paired with the channel the blocked task_await_input waiter takes the client's tasks/update response from. The channel is buffered (size 1) and receives exactly one value — the key is removed from the pending map in the same critical section that delivers, so a key can never be answered twice.
Fields
method::String: The input request's method (e.g.elicitation/create)params::Any: The input request's params (a Dict, ornothingfor none)channel::Channel{Any}: Delivery channel to the blocked handler; closed (never fed) when the task is cancelled, unwinding the waiter
ModelContextProtocol.TaskDetachState — Type
TaskDetachState(transport, route)Per-call state for a detachable modern-era tools/call (tasks extension, SEP-2663). Created when the call is spawned off-loop with its response route captured; task_detach(ctx) uses it to mint the task and deliver the CreateTaskResult, and the spawn wrapper uses it to learn whether the handler detached. All access is under lock.
Fields
lock::ReentrantLock: Guardsrecord/closedagainst the detach/finish racetransport::Any: The serving transport at spawn timeroute::Any: The captured response route (seecapture_response_route)required_scopes::Vector{String}: The tool'srequired_scopes, recorded onto the minted task for per-request re-authorization of the extension surfacerecord::Union{TaskRecord,Nothing}: The minted task, published the moment it is durably created — BEFORE any fallible wire building or delivery, so a failure in between can never orphan a hidden non-terminal recordclosed::Bool: Set when the handler has returned — a latetask_detach(e.g. from a stray child task) must fail rather than deliver a second responsecreate_delivered::Bool: Set once theCreateTaskResultdelivery was attempted; while false, the request is still owed a response (the spawn wrapper answers -32603 if the handoff died between task creation and delivery)
ModelContextProtocol.TaskRecord — Type
TaskRecordMutable record of one server-side task (a task-augmented request execution).
Fields
task_id::String: Receiver-generated unique identifier (cryptographically random)status::String: One of "working", "input_required", "completed", "failed", "cancelled"status_message::Union{String,Nothing}: Optional human-readable status detailcreated_at::DateTime: UTC creation timestamplast_updated_at::DateTime: UTC timestamp of the last status changettl_ms::Union{Int,Nothing}: Actual retention duration from creation;nothing= unlimitedpoll_interval_ms::Union{Int,Nothing}: Suggested client polling intervalprincipal::Union{String,Nothing}: Authorization binding (authenticated subject),nothingwhen unauthenticatedmethod::String: The originating request method (e.g. "tools/call")era::Symbol::legacyfor SEP-1686 experimental tasks (2025-11-25 sessions),:extfor the modern-eraio.modelcontextprotocol/tasksextension (SEP-2663). The eras are wire-incompatible and never serve each other's recordsrequired_scopes::Vector{String}: The originating tool'srequired_scopes, re-checked on every extension-era task request (SEP-2663 requires authorization on each task-related request — a later token for the same subject but without the tool's scopes must not read the result). Empty when the tool declares noneresult::Union{CallToolResult,Nothing}: Final result when the underlying call succeeded (or failed viaisError)error::Union{ErrorInfo,Nothing}: Final JSON-RPC error when the underlying call erroreddone::Base.Event: Set exactly once when the task reaches a terminal statuscancel_requested::Threads.Atomic{Bool}: Set once tasks/cancel is accepted; atomic so handlers can poll it lock-free from worker threads viatask_cancelled(ctx)pending_inputs::LittleDict{String,PendingTaskInput}: Outstanding mid-task input requests keyed by server-minted id (extension era only; insertion-ordered, soinputRequestsserializes in issue order). Non-empty exactly while the task isinput_requiredinput_key_counter::Int: Monotone counter mintingpending_inputskeys — a key is never reused over the task's lifetime, even after its request is answered (SEP-2663 key-uniqueness rule)
All mutation goes through the owning TaskStore under its lock.
ModelContextProtocol.TaskStore — Type
TaskStore(; default_ttl_ms=TASK_DEFAULT_TTL_MS, max_ttl_ms=TASK_MAX_TTL_MS,
poll_interval_ms=TASK_POLL_INTERVAL_MS, page_size=TASKS_PAGE_SIZE)Thread-safe registry of server-side tasks.
Fields
lock::ReentrantLock: Guards all record access and mutationtasks::Dict{String,TaskRecord}: Records by task iddefault_ttl_ms::Int: ttl applied when the requestor does not ask for onemax_ttl_ms::Int: Upper bound applied to requested ttlspoll_interval_ms::Int: Suggested polling interval included in task responsespage_size::Int: Page size for tasks/list cursor paginationon_status_change::Base.RefValue{Any}: Optional hookrecord -> Nothingfired after every status transition, while the store lock is held (see_fire_status_change); installed for the tasks extension'snotifications/tasks.nothingdisables itnotification_seq::Threads.Atomic{Int}: Monotone sequence stamped on every enqueued status notification. Atomic on purpose: it is written at transition sites (under the store lock) but read for registration thresholds under the unrelated registry lock — a plainRefwould be a data race on a threaded runtime. Subscriptions record the counter at registration and receive only later-stamped events, so a queued-but-undrained backlog never replays older states to a freshly registered stream
ModelContextProtocol._fire_status_change — Method
_fire_status_change(store::TaskStore, record::TaskRecord) -> NothingFire the store's status-change hook for a record whose status just changed. Called at every transition site WHILE the store lock is held — the hook builds the task's wire snapshot (which requires the lock) and ENQUEUES it (no transport I/O happens under the store lock; a dedicated dispatcher task broadcasts from the queue, see install_task_notifications!). A throwing hook is swallowed: a notification must never break the transition that triggered it.
ModelContextProtocol.cancel_task! — Method
cancel_task!(store::TaskStore, record::TaskRecord) -> BoolTransition a task to "cancelled". Returns false without mutating when the task is already terminal (the handler maps that to a -32602 error per spec). Sets cancel_requested so cooperative handlers can observe it via task_cancelled(ctx), and unblocks any task_await_input waiter by draining the pending input requests.
ModelContextProtocol.create_task! — Method
create_task!(store::TaskStore, method::String;
requested_ttl_ms=nothing, principal=nothing, era=:legacy,
status_message=nothing) -> TaskRecordCreate a new task record in "working" status with a cryptographically random task id. The requested ttl is clamped to the store's max_ttl_ms; when absent the store's default_ttl_ms applies.
ModelContextProtocol.drain_pending_inputs! — Method
drain_pending_inputs!(record::TaskRecord) -> NothingClose and clear every outstanding mid-task input request on a task entering a terminal status: a blocked task_await_input waiter observes its channel closing and unwinds (there is nothing left that could ever feed it). Caller must hold the store lock — which is also what makes close-vs-deliver atomic: tasks/update delivers under the same lock, so a channel is either fed exactly once or closed, never both.
ModelContextProtocol.expire_parked_input! — Method
expire_parked_input!(store::TaskStore, record::TaskRecord, now_utc::DateTime) -> BoolFail an extension-era task whose ttl elapsed while parked in input_required: a task past its ttl that is waiting on CLIENT input is abandoned — the client the server is waiting on can no longer use the result — so it is terminalized (status failed, error inlined) and its pending inputs drained, unwinding the blocked task_await_input waiter. A no-op (returning false) for any record not in exactly that state, so the deadline timer and the store sweep can both call it and whichever runs first wins. Caller must hold the store lock.
ModelContextProtocol.finish_task! — Method
finish_task!(store::TaskStore, record::TaskRecord,
outcome::Union{CallToolResult,ErrorInfo}) -> BoolTransition a task to its terminal status from a completed execution. An ErrorInfo (a JSON-RPC error) is always "failed". For a CallToolResult the eras diverge: legacy (SEP-1686) maps is_error to "failed", while the extension era (SEP-2663) requires "completed" for ANY result — "failed" is reserved for JSON-RPC errors, and a tool-level isError:true result completes with the result inlined. Returns false without mutating when the task is already terminal (e.g. cancelled while the work was still running — cancelled tasks MUST stay cancelled, so the outcome is discarded).
ModelContextProtocol.get_task — Method
get_task(store::TaskStore, task_id::String,
principal::Union{String,Nothing}; era=:legacy) -> Union{TaskRecord,Nothing}Look up a task by id, enforcing authorization-context binding: a record is only returned when its stored principal matches the requestor's AND it belongs to the requested era (legacy sessions cannot see extension tasks and vice versa — the wire shapes are incompatible). A mismatch returns nothing (indistinguishable from "not found", so task existence is not leaked).
ModelContextProtocol.iso8601_utc — Method
iso8601_utc(dt::DateTime) -> StringFormat a UTC DateTime as an ISO 8601 / RFC 3339 timestamp with a Z suffix.
ModelContextProtocol.list_tasks — Method
list_tasks(store::TaskStore, principal::Union{String,Nothing},
cursor::Union{String,Nothing}; era=:legacy)
-> Tuple{Vector{TaskRecord},Union{String,Nothing}}Return one page of the requestor's tasks (oldest first) and the next-page cursor, or nothing for the cursor when no further pages exist. Only tasks bound to the same principal AND era are visible (tasks/list exists only in the legacy era; extension records must never leak into it — the extension deliberately has no list, so one caller's task ids cannot be exposed to another). Throws ArgumentError for an invalid cursor (mapped to -32602 by the handler).
ModelContextProtocol.sweep_expired! — Method
sweep_expired!(store::TaskStore) -> NothingDelete terminal task records whose ttl has elapsed, and fail expired extension-era tasks still parked in input_required (see expire_parked_input! — here as a backstop; the clock-driven per-wait deadline timer in task_await_input is what guarantees the transition without further store activity). Once failed, such a record is terminal AND expired, so the next sweep deletes it — a post-expiry poll observes either the failed record briefly (when its own sweep is the one that just terminalized it) or task-not-found, timing-dependent; neither is promised. Other non-terminal records are retained past their ttl (the spec permits but does not require deleting those, and their background work may still be running). Caller must hold store.lock.
ModelContextProtocol.task_is_expired — Method
task_is_expired(record::TaskRecord, now_utc::DateTime) -> BoolReturn whether the task's ttl (counted from creation) has elapsed. Unlimited (ttl_ms === nothing) tasks never expire.
ModelContextProtocol.task_is_terminal — Method
task_is_terminal(record::TaskRecord) -> BoolReturn whether the task is in a terminal status ("completed", "failed", or "cancelled").
ModelContextProtocol.task_wire — Method
task_wire(record::TaskRecord) -> LittleDict{String,Any}Serialize a task record to the spec wire shape: taskId, status, optional statusMessage, createdAt/lastUpdatedAt (ISO 8601 UTC), ttl (always present; null for unlimited), and optional pollInterval.
ModelContextProtocol.SubscriptionFilter — Type
SubscriptionFilter(; tools_list_changed=false, prompts_list_changed=false,
resources_list_changed=false, resource_uris=Set{String}(),
task_ids=Set{String}())The notification types a subscriptions/listen stream opted into. A server MUST NOT send notification types the client did not explicitly request, so every delivery is checked against this filter.
Fields
tools_list_changed::Bool: delivernotifications/tools/list_changedprompts_list_changed::Bool: delivernotifications/prompts/list_changedresources_list_changed::Bool: delivernotifications/resources/list_changedresource_uris::Set{String}: delivernotifications/resources/updatedfor these URIs (a set: membership is checked on every update broadcast)task_ids::Set{String}: delivernotifications/tasksstatus updates for these task ids (tasks extension, SEP-2663; only ids the requestor couldtasks/getare ever agreed to)
ModelContextProtocol.SubscriptionRecord — Type
SubscriptionRecord(id, filter, route, transport,
task_principal=nothing, task_scopes=Set{String}())One active subscriptions/listen stream.
Fields
id::Union{String,Int}: the listen request's JSON-RPC id — also theio.modelcontextprotocol/subscriptionIdevery message on the stream carriesfilter::SubscriptionFilter: the notification types this stream opted intoroute::Any: the transport route handle the notifications are delivered on (nothingfor stream transports like stdio, which share one channel)transport::Any: the transport to deliver over (Transport; typedAnyto avoid include-order coupling)task_principal::Union{String,Nothing}: the listen requestor's extension-task principal, re-checked at everynotifications/tasksdeliverytask_scopes::Set{String}: the listen requestor's token scopes, re-checked against the task'srequired_scopesat everynotifications/tasksdelivery — a task whose authorization requirements changed after the listen must not keep leaking status to a stream that could no longertasks/getittask_seq::Int: the task-notification sequence at registration; only events stamped LATER are delivered to this stream, so a queued-but-undrained backlog never replays states older than the stream's own initial snapshot
ModelContextProtocol.SubscriptionRegistry — Type
SubscriptionRegistry()Registry of active subscriptions/listen streams. Guarded by a lock: the single server loop registers streams while HTTP connection tasks and background task executions can broadcast notifications concurrently. Deliveries happen WHILE holding this lock (all delivery paths enqueue without blocking), which is what guarantees the acknowledged-first and nothing-after-the-closing-result orderings.
Lock ordering: registry.lock may be held when a delivery takes the HTTP transport's channels_lock, never the reverse — nothing takes registry.lock while holding channels_lock.
Fields
subs::Vector{SubscriptionRecord}: active subscriptionslock::ReentrantLock: guardssubs
ModelContextProtocol.filter_to_wire — Method
filter_to_wire(f::SubscriptionFilter) -> LittleDict{String,Any}Serialize a filter to the wire shape used in the acknowledgment's notifications field, which reflects the subset the server agreed to honor. Types not subscribed are omitted, and the resource URIs are emitted sorted (the in-memory set has no stable order).
Arguments
f::SubscriptionFilter: The filter
Returns
LittleDict{String,Any}: The honored subset
ModelContextProtocol.filter_wants — Function
filter_wants(f::SubscriptionFilter, method::String,
uri::Union{String,Nothing}=nothing,
task_id::Union{String,Nothing}=nothing) -> BoolWhether a notification of method (for resource updates, of uri; for task status updates, of task_id) was opted into.
Arguments
f::SubscriptionFilter: The subscription's filtermethod::String: The notification methoduri::Union{String,Nothing}: The resource URI fornotifications/resources/updatedtask_id::Union{String,Nothing}: The task id fornotifications/tasks
Returns
Bool: true when the notification may be delivered on this stream
ModelContextProtocol.parse_subscription_filter — Method
parse_subscription_filter(notifications) -> Union{SubscriptionFilter,String}Validate and parse the notifications filter object of a subscriptions/listen request. Returns the parsed filter, or a violation message the caller must reject with -32602: the filter must be an object, the *ListChanged flags booleans, resourceSubscriptions an array of at most MAX_RESOURCE_SUBSCRIPTIONS strings, and at least one notification type must be requested — a malformed filter must not silently establish a long-lived stream that can never deliver anything.
Unknown keys are ignored (forward compatibility), and requesting types this server cannot deliver is NOT a violation: the honored subset in the acknowledgment is how the server communicates what it will actually send (see handle_subscriptions_listen).
Arguments
notifications: The request'sparams.notificationsvalue (any JSON value)
Returns
Union{SubscriptionFilter,String}: The parsed filter, or the violation
Transport Implementation
ModelContextProtocol.TransportError — Type
TransportError(message::String) <: ExceptionException type for transport-specific errors.
Fields
message::String: The error message describing what went wrong
ModelContextProtocol.capture_response_route — Method
capture_response_route(transport::Transport) -> AnyCapture a route handle for delivering the CURRENT request's response later, from outside the server loop (used by tasks/result, which must block until the task completes without blocking the loop). The returned handle is passed to deliver_response.
The default returns nothing — for stream transports like stdio, responses carry their correlation in the JSON-RPC id, so no per-request route exists. Transports that route responses per request (HTTP) override this to detach and return the current request's route so the loop can move on to the next request.
Arguments
transport::Transport: The transport instance
Returns
- An opaque route handle understood by
deliver_responsefor this transport
ModelContextProtocol.close — Function
close(transport::Transport) -> NothingClose the transport connection and clean up resources.
Arguments
transport::Transport: The transport instance to close
Returns
Nothing
ModelContextProtocol.deliver_log_notification — Method
deliver_log_notification(transport::Transport, route::Any, message::String) -> BoolDeliver a request-scoped log notification (ModernRequestLogger) on a request's response route. Distinct from deliver_notification because the failure policy differs: a subscriptions/listen stream that cannot keep up is load-shed by CLOSING it, but a request's response channel must never be closed under log pressure — the final response still has to travel it. Implementations drop the record (returning false, which sends it to the logger's fallback stream) rather than sacrifice the channel.
The default delegates to deliver_notification (correct for stdio's shared stream, which has no per-request channel to protect).
Arguments
transport::Transport: The transport instanceroute::Any: The request's captured notification routemessage::String: The serialized JSON-RPC notification
Returns
Bool: true when the notification was delivered
ModelContextProtocol.deliver_notification — Method
deliver_notification(transport::Transport, route::Any, message::String) -> BoolDeliver a notification on a route captured earlier with capture_response_route, used by subscriptions/listen streams (whose request never completes, so its route carries notifications instead). Returns whether delivery succeeded — false means the client is gone and the subscription should be pruned.
The default writes to the shared stream (correct for stdio, where all messages share one channel and the io.modelcontextprotocol/subscriptionId tag demultiplexes them). Transports that route per request (HTTP) override this to push onto that request's response stream.
Arguments
transport::Transport: The transport instanceroute::Any: The handle returned bycapture_response_routemessage::String: The serialized JSON-RPC notification
Returns
Bool: true when the notification was delivered
ModelContextProtocol.deliver_response — Method
deliver_response(transport::Transport, route::Any, message::String) -> NothingDeliver a serialized JSON-RPC response for a request whose route was captured earlier with capture_response_route. Safe to call from a background task. The default ignores the route and writes to the shared stream (correct for stdio, where write_message is lock-serialized).
Arguments
transport::Transport: The transport instanceroute::Any: The handle returned bycapture_response_routemessage::String: The serialized JSON-RPC response
Returns
Nothing
ModelContextProtocol.flush — Method
flush(transport::Transport) -> NothingFlush any buffered data in the transport. Default implementation does nothing.
Arguments
transport::Transport: The transport instance to flush
Returns
Nothing
ModelContextProtocol.is_connected — Function
is_connected(transport::Transport) -> BoolCheck if the transport is currently connected and operational.
Arguments
transport::Transport: The transport instance to check
Returns
Bool: true if connected and ready, false otherwise
ModelContextProtocol.notification_route — Method
notification_route(transport::Transport) -> AnyReturn the route handle identifying the request the transport just handed to the server loop, for request-scoped notification delivery. The loop stores it in task-local storage around message processing so send_notification can route notifications emitted during synchronous handling onto that request's response stream. The default returns nothing — stdio has a single shared stream, so notifications need no routing. HTTP overrides this with the current request's ID.
Arguments
transport::Transport: The transport instance
Returns
- An opaque route handle, or
nothingwhen the transport needs no routing
ModelContextProtocol.pending_auth_context — Method
pending_auth_context(transport::Transport) -> Union{Nothing,Any}Return the authenticated user associated with the message most recently read from transport, or nothing when the transport has no per-request authentication (e.g. stdio). Transports that authenticate requests override this; the default is nothing.
ModelContextProtocol.pending_param_headers — Method
pending_param_headers(transport::Transport) -> Union{Nothing,Dict{String,Any}}Return the Mcp-Param-* custom headers (SEP-2243 parameter mirroring) of the message most recently read from transport: a Dict keyed by LOWERCASED header suffix, with String values (OWS-stripped) or :invalid for duplicated/unsafe headers — or nothing when the transport carries no HTTP headers (e.g. stdio), which disables the mirroring validation entirely. HTTP overrides this; the default is nothing.
ModelContextProtocol.read_message — Function
read_message(transport::Transport) -> Union{String,Nothing}Read a single message from the transport.
Arguments
transport::Transport: The transport instance to read from
Returns
Union{String,Nothing}: The message string if available, or nothing if no message or connection closed
ModelContextProtocol.route_alive — Method
route_alive(transport::Transport, route::Any) -> BoolWhether the client behind a captured response route is still reachable — used by subscription broadcasts to sweep dead streams without writing anything to them.
The default returns true: stream transports (stdio) have no per-request route whose death is observable here, and their delivery attempt reports failure itself. HTTP overrides this to check whether the route's channel still exists and is open.
Arguments
transport::Transport: The transport instanceroute::Any: The handle returned bycapture_response_route
Returns
Bool: true when the route may still deliver
ModelContextProtocol.send_notification — Method
send_notification(transport::Transport, message::String) -> NothingDeliver a server-to-client JSON-RPC notification over transport.
The default writes the message directly — correct for stdio, where notifications and responses share one stream. Transports that multiplex per-request responses (e.g. HTTP, where write_message routes to the calling request's response channel) override this to send notifications over a separate out-of-band channel, so a mid-request notification never corrupts that request's response.
Arguments
transport::Transport: The transport instance to send overmessage::String: The serialized JSON-RPC notification
Returns
Nothing
ModelContextProtocol.set_negotiated_version! — Method
set_negotiated_version!(transport::Transport, version::String) -> NothingInform the transport of the protocol version negotiated during initialize, so transports that advertise a version per response (e.g. the HTTP MCP-Protocol-Version header) echo the negotiated one rather than a static default. Default is a no-op (stdio carries no version metadata).
Arguments
transport::Transport: The transport instance to updateversion::String: The negotiated MCP protocol version
Returns
Nothing
ModelContextProtocol.write_message — Function
write_message(transport::Transport, message::String) -> NothingWrite a message to the transport.
Arguments
transport::Transport: The transport instance to write tomessage::String: The message to send
Returns
Nothing
Throws
TransportError: If the message cannot be sent
ModelContextProtocol.close — Method
close(transport::StdioTransport) -> NothingMark the transport as closed. Does not actually close stdin/stdout.
Arguments
transport::StdioTransport: The stdio transport instance
Returns
Nothing
ModelContextProtocol.flush — Method
flush(transport::StdioTransport) -> NothingFlush the output stream.
Arguments
transport::StdioTransport: The stdio transport instance
Returns
Nothing
ModelContextProtocol.is_connected — Method
is_connected(transport::StdioTransport) -> BoolCheck if the stdio transport is connected.
Arguments
transport::StdioTransport: The stdio transport instance
Returns
Bool: Connection status
ModelContextProtocol.read_message — Method
read_message(transport::StdioTransport) -> Union{String,Nothing}Read a line from the input stream.
Arguments
transport::StdioTransport: The stdio transport instance
Returns
Union{String,Nothing}: The message string, or nothing if empty or EOF
ModelContextProtocol.write_message — Method
write_message(transport::StdioTransport, message::String) -> NothingWrite a message to the output stream with a newline.
Arguments
transport::StdioTransport: The stdio transport instancemessage::String: The message to write
Returns
Nothing
Throws
TransportError: If writing fails
ModelContextProtocol.QueuedHttpRequest — Type
QueuedHttpRequest(id, body, user, param_headers=nothing)Envelope for a request on the HTTP work queue. Carries the per-request authenticated user (or nothing) and the request's Mcp-Param-* custom headers (SEP-2243 parameter mirroring; nothing for messages that carry none) from the concurrent connection handler to the single server loop, so per-request context travels with the request rather than via shared transport state.
ModelContextProtocol.accepts_sse — Method
accepts_sse(accept_header::AbstractString) -> BoolWhether an Accept header admits a text/event-stream response, per media-range matching: comma-separated ranges, media types compared case-insensitively with parameters stripped, text/* and */* admitted, and q=0 a refusal. The MOST SPECIFIC matching range decides (RFC 9110 precedence): exact text/event-stream over text/* over */* — so text/event-stream;q=0, text/*;q=1 is a refusal even though a laxer range matches. A bare substring test gets all of this wrong.
Pass the COMBINED value when the request repeats the Accept field (repeated fields are equivalent to their comma-joined concatenation).
Arguments
accept_header::AbstractString: The request's (combined)Acceptheader value
Returns
Bool: true when the client can consume an SSE response
ModelContextProtocol.broadcast_to_sse — Method
broadcast_to_sse(transport::HttpTransport, message::String; event::String="message") -> NothingBroadcast a message immediately to all SSE streams.
Arguments
transport::HttpTransport: The transport instancemessage::String: The message to broadcastevent::String: The event type (default: "message")
Returns
Nothing
ModelContextProtocol.capture_response_route — Method
capture_response_route(transport::HttpTransport) -> Union{String,Nothing}Detach the current request's response route so its response can be delivered later from a background task (see deliver_response). Clears current_request_id so the loop's subsequent write_message calls cannot route into this request's channel.
ModelContextProtocol.close — Method
close(transport::HttpTransport) -> NothingStop the HTTP server and close all connections.
Arguments
transport::HttpTransport: The transport instance
Returns
Nothing
ModelContextProtocol.collect_param_headers — Method
collect_param_headers(request) -> Dict{String,Any}Collect the request's Mcp-Param-* custom headers (SEP-2243 parameter mirroring) into a Dict keyed by LOWERCASED header suffix. Values are OWS-stripped Strings, or :invalid when the header is duplicated or carries unsafe bytes (the same rules mcp_standard_header applies) — the preflight in handle_modern_request rejects :invalid entries with -32020. Always returns a Dict (possibly empty) for HTTP requests: an EMPTY Dict still arms the missing-header-with-body-value check, which nothing (a transport with no headers at all, e.g. stdio) disables.
ModelContextProtocol.decode_mcp_header_value — Method
decode_mcp_header_value(value::AbstractString) -> Union{String,Nothing}Decode a standard-header value per SEP-2243: a =?base64?...?= sentinel wraps a Base64-encoded UTF-8 payload (used when the raw value is not header-safe). The Base64 is validated STRICTLY — canonical alphabet, correct padding, length a multiple of four — because Julia's decoder is permissive (it ignores invalid characters and missing padding), and SEP-2243 requires such values to be rejected, not fuzzily matched. The decoded bytes must be valid UTF-8. Returns nothing when the value must cause a -32020 rejection.
Arguments
value::AbstractString: The header value (already whitespace-stripped)
Returns
Union{String,Nothing}: The decoded value, ornothingwhen malformed
ModelContextProtocol.deliver_log_notification — Method
deliver_log_notification(transport::HttpTransport, route, message::String) -> BoolPush a request-scoped log notification onto the request's response stream. Unlike deliver_notification, backlog pressure NEVER closes the channel — the request's final response still has to travel it, and load-shedding it away because a stalled client let log records pile up would destroy the response. Past the cap the record is simply dropped (false), sending it to the logger's fallback stream instead.
ModelContextProtocol.deliver_notification — Method
deliver_notification(transport::HttpTransport, route, message::String) -> BoolPush a notification onto the response stream of the request identified by route (captured via capture_response_route) — the delivery path for subscriptions/listen streams. Returns false when that route is gone (client disconnected), so the caller can prune the subscription.
A listen stream lives arbitrarily long, so — unlike ordinary request channels, whose buffering is bounded by the request's own lifetime — its backlog must be capped: a reader that stopped draining would otherwise accumulate every notification forever. At LISTEN_BACKLOG_CAP pending items the stream is load-shed: its channel is closed (which ends the connection handler after it drains what is already buffered) and delivery is reported failed so the caller prunes the subscription.
ModelContextProtocol.deliver_response — Method
deliver_response(transport::HttpTransport, route::Union{String,Nothing}, message::String) -> NothingDeliver a deferred response to the request identified by route (captured earlier via capture_response_route). The HTTP connection handler is still blocked on the request's response channel, so the POST stays open until this delivers — which is exactly the blocking behavior tasks/result requires. Dropped silently when the client has disconnected (its channel is gone or closed).
ModelContextProtocol.end_response — Method
end_response(transport::HttpTransport) -> NothingDeprecated: No longer needed as HTTP transport now sends complete responses. This method exists for backward compatibility but does nothing.
Arguments
transport::HttpTransport: The transport instance
Returns
Nothing
ModelContextProtocol.format_sse_event — Method
format_sse_event(data::String; event::Union{String,Nothing}=nothing, id::Union{Int64,String,Nothing}=nothing) -> StringFormat a message as a Server-Sent Event.
Arguments
data::String: The data to sendevent::Union{String,Nothing}: Optional event typeid::Union{Int64,String,Nothing}: Optional event ID
Returns
String: Formatted SSE event
ModelContextProtocol.generate_session_id — Method
generate_session_id() -> StringGenerate a cryptographically secure session ID that meets MCP requirements. Must contain only visible ASCII characters (0x21 to 0x7E).
Returns
String: A valid session ID
ModelContextProtocol.handle_request — Method
handle_request(transport::HttpTransport, stream::HTTP.Stream)Handle incoming HTTP requests following the Streamable HTTP specification. Returns a single JSON response per request.
Arguments
transport::HttpTransport: The transport instancestream::HTTP.Stream: The HTTP stream
Returns
Nothing
ModelContextProtocol.handle_sse_stream — Method
handle_sse_stream(transport::HttpTransport, stream::HTTP.Stream, stream_id::String)Handle a Server-Sent Events connection for notifications and streaming responses.
Arguments
transport::HttpTransport: The transport instancestream::HTTP.Stream: The HTTP streamstream_id::String: Unique identifier for this SSE stream
Returns
Nothing
ModelContextProtocol.is_connected — Method
is_connected(transport::HttpTransport) -> BoolCheck if the HTTP server is running and accepting connections.
Arguments
transport::HttpTransport: The transport instance
Returns
Bool: true if connected, false otherwise
ModelContextProtocol.is_loopback_host — Method
is_loopback_host(host::AbstractString) -> BoolDetermine whether a hostname refers to the local loopback: localhost (optionally with a trailing dot), any 127.0.0.0/8 IPv4 address, ::1, or an IPv4-mapped IPv6 loopback (::ffff:127.x.y.z). String-list matching is not enough here — binding or addressing via 127.0.0.2 is just as local as 127.0.0.1.
Arguments
host::AbstractString: Hostname, IP literal, or bracketed IPv6 literal
Returns
Bool: true if the host is loopback
ModelContextProtocol.is_valid_session_id — Method
is_valid_session_id(session_id::String) -> BoolValidate that a session ID contains only visible ASCII characters (0x21 to 0x7E).
Arguments
session_id::String: The session ID to validate
Returns
Bool: true if valid, false otherwise
ModelContextProtocol.mcp_standard_header — Method
mcp_standard_header(request, name::String) -> Union{String,Nothing,Symbol}Fetch a SEP-2243 standard header strictly: header names are matched case-insensitively across ALL header instances; duplicates (a smuggling vector — a gateway may honor a different copy than the backend) and values containing non-visible-ASCII bytes (NUL/control/8-bit, which HTTP.jl's parser admits but intermediaries interpret divergently) are rejected. Returns the single whitespace-stripped value, nothing when absent, or :invalid when the header must cause a -32020 rejection.
Arguments
request: The HTTP requestname::String: The header name
Returns
Union{String,Nothing,Symbol}: Value,nothing(absent), or:invalid
ModelContextProtocol.modern_error_http_status — Method
modern_error_http_status(payload::String) -> IntMap a modern-era JSON-RPC response to its HTTP status per the 2026-07-28 transport: -32601 (method not found) → 404; the protocol validation errors — -32020 HeaderMismatch, -32021 MissingRequiredClientCapability, -32022 UnsupportedProtocolVersion — → 400; everything else (results and application-level errors) → 200.
Arguments
payload::String: The serialized JSON-RPC response
Returns
Int: The HTTP status code to use
ModelContextProtocol.modern_header_violation — Method
modern_header_violation(request, msg, body_version) -> Union{String,Nothing}Validate the SEP-2243 standard request headers of a modern-era POST against its body: MCP-Protocol-Version and Mcp-Method are required on every request and must match the body's _meta protocol version and method; Mcp-Name is required on tools/call/prompts/get (mirroring params.name) and resources/read (mirroring params.uri), with the Base64 sentinel decoded before comparison. Header names are case-insensitive, duplicates and unsafe bytes are rejected (mcp_standard_header), values are compared case-sensitively after whitespace stripping. (A request whose headers claim a modern era while the body carries no modern _meta never reaches this function — the caller rejects it as a missing required field, -32602.)
Arguments
request: The HTTP request (for header access)msg: The parsed JSON body (aJSON3.Object)body_version: The body's_metaprotocol version
Returns
Union{String,Nothing}: A violation description for a -32020 HeaderMismatch, ornothingwhen the headers validate
ModelContextProtocol.notification_route — Method
notification_route(transport::HttpTransport) -> Union{String,Nothing}Return the HTTP request ID of the message just read from the queue, used by the server loop as the request-scoped notification route (see the base notification_route docstring).
ModelContextProtocol.parse_host_header — Method
parse_host_header(hostport::AbstractString) -> Union{String,Nothing}Parse a Host-header style host[:port] value strictly, returning the lowercased hostname or nothing when the value is malformed (userinfo, multiple colons on a non-bracketed host, junk after a bracketed IPv6 literal, non-numeric port). Malformed values must be REJECTED by the DNS-rebinding guard, not leniently truncated into something that looks local ([::1]evil.example must not read as [::1]).
Arguments
hostport::AbstractString: A Host-header style value
Returns
Union{String,Nothing}: The lowercased hostname (brackets kept for IPv6 literals), ornothingwhen malformed
ModelContextProtocol.pending_auth_context — Method
pending_auth_context(transport::HttpTransport) -> Union{AuthenticatedUser,Nothing}Return the authenticated user of the message most recently read from the queue (set in read_message, consumed immediately by the single server loop). This is how the per-request identity reaches RequestContext.authenticated_user; handlers should read it from the request context, not from the transport.
ModelContextProtocol.pending_param_headers — Method
pending_param_headers(transport::HttpTransport) -> Union{Nothing,Dict{String,Any}}Return the Mcp-Param-* headers of the message most recently read from the queue (set in read_message, consumed immediately by the single server loop) — the SEP-2243 parameter-mirroring context validated by the handle_modern_request preflight.
ModelContextProtocol.read_message — Method
read_message(transport::HttpTransport) -> Union{String,Nothing}Read a message from the request queue. Waits a BOUNDED interval and returns nothing when no request arrives, so the server loop regularly re-checks its run condition: stop! must be able to end the loop while the transport is still open (graceful subscriptions/listen closure delivers on the open transport, then the transport is closed) — a blocking take! would pin the loop until the next request.
Arguments
transport::HttpTransport: The transport instance
Returns
Union{String,Nothing}: The message string, or nothing when no request arrived (or the transport disconnected)
ModelContextProtocol.rebinding_violation — Method
rebinding_violation(host_header, origin_header, allowed_hosts, allowed_origins) -> Union{String,Nothing}Check Host and Origin headers against DNS-rebinding attacks on a loopback-bound server (GHSA-w48q-cv73-mx4w class): a malicious website resolves its own domain to 127.0.0.1 and drives the local server from the victim's browser. A legitimate local client sends a loopback Host; the attack necessarily carries the attacker's hostname. Malformed Host values are violations (see parse_host_header). allowed_hosts applies to the Host header only; Origin is admitted by loopback hostname or an exact allowed_origins match — a proxy hostname in allowed_hosts deliberately does NOT admit browser origins on that host.
Arguments
host_header: The request's Host header value ("" when absent)origin_header: The request's Origin header value ("" when absent)allowed_hosts: Extra hostnames accepted in Host (e.g. a reverse-proxy domain)allowed_origins: Full origins accepted in Origin (exact match, existing semantics)
Returns
Union{String,Nothing}: A human-readable violation description, ornothingif the request is acceptable
ModelContextProtocol.route_alive — Method
route_alive(transport::HttpTransport, route) -> BoolWhether a captured response route still has a live consumer: its channel is still registered and open. The connection handler unregisters and closes the channel when its client disconnects (or its stream is load-shed), so a dead route shows up here without anything being written to it.
ModelContextProtocol.send_notification — Method
send_notification(transport::HttpTransport, notification::String) -> NothingSend a notification. A notification emitted while the server loop is synchronously handling a request (progress, log messages) is request-scoped: it is routed onto that request's response channel and delivered on the POST's SSE response stream, per Streamable HTTP. Anything else — notifications from background tasks (MCP Tasks status updates) or emitted outside request handling — goes to the standalone GET SSE notification stream.
The request route is read from the server loop's task-local storage (set in run_server_loop), so background tasks — which never inherit it — can't misroute their notifications into whatever request the loop happens to be processing.
Arguments
transport::HttpTransport: The transport instancenotification::String: The notification message to send
Returns
Nothing
ModelContextProtocol.set_negotiated_version! — Method
set_negotiated_version!(transport::HttpTransport, version::String) -> NothingUpdate the version advertised in MCP-Protocol-Version response headers (and accepted in request headers) to the version negotiated during initialize, so per-request headers echo what the initialize response returned.
ModelContextProtocol.split_outside_quotes — Method
split_outside_quotes(s::AbstractString, delim::Char) -> Vector{String}Split s on delim occurrences that lie OUTSIDE double-quoted strings, honoring backslash escapes inside quotes (RFC 9110 quoted-string). Header parameters may legally quote separator characters (profile="a,b"), so a naive split corrupts the ranges around them.
Arguments
s::AbstractString: The header text to splitdelim::Char: The separator character
Returns
Vector{String}: The parts (quotes preserved verbatim)
ModelContextProtocol.write_message — Method
write_message(transport::HttpTransport, message::String) -> NothingWrite a message to the current request's response channel. The request handler will send this as the HTTP response.
Arguments
transport::HttpTransport: The transport instancemessage::String: The message to send
Returns
Nothing
Authentication Implementation
ModelContextProtocol.check_allowlist — Method
check_allowlist(user::AuthenticatedUser, allowlist::Set{String};
case_insensitive::Bool=true) -> BoolCheck whether user is in the allowlist, by username then by subject.
Username matching honors case_insensitive (default true) because identity providers vary or normalize username case (e.g. Keycloak lowercases GitHub logins). The opaque OAuth subject is ALWAYS matched exactly — case-folding a stable identifier could collide two distinct principals.
Arguments
user::AuthenticatedUser: The authenticated userallowlist::Set{String}: Set of allowed usernames or subjectscase_insensitive::Bool=true: Match usernames case-insensitively
Returns
true if user is allowed.
ModelContextProtocol.add_token! — Method
add_token!(validator::SimpleTokenValidator, token::String, user::AuthenticatedUser)Add a valid token to the validator.
ModelContextProtocol.decode_jwt_header — Method
decode_jwt_header(token::String) -> Union{Dict{String,Any},Nothing}Decode the JWT header (first segment) without verification. Returns nothing if the token format is invalid.
ModelContextProtocol.decode_jwt_payload — Method
decode_jwt_payload(token::String) -> Union{Dict{String,Any},Nothing}Decode JWT payload without verification (for claim inspection). Returns nothing if token format is invalid.
ModelContextProtocol.fetch_jwks_http_body — Method
fetch_jwks_http_body(url::String) -> Union{String,Nothing}GET a JWKS over HTTP(S) with bounded connect/read timeouts, streaming the body and aborting once MAX_JWKS_BYTES is exceeded. Returns the body string on a 200, or nothing on non-200, oversize, or transport error.
ModelContextProtocol.fetch_jwks_keys — Method
fetch_jwks_keys(url::String) -> Union{Vector{Dict{String,Any}},Nothing}Fetch and parse the keys array of a JWKS document from an http(s):// or file:// URL. Network fetches use bounded connect/read timeouts and reject responses larger than MAX_JWKS_BYTES (read is aborted once the cap is exceeded, so an oversized or unbounded body cannot exhaust memory). Returns nothing on any failure (fetch, oversize, parse, or missing keys field) — callers fail closed.
ModelContextProtocol.lookup_jwks_key! — Method
lookup_jwks_key!(validator::JWKSValidator, kid::String) -> Union{JWTs.JWK,Nothing}Look up a verification key by kid, re-fetching the JWKS on a miss (key rotation) subject to the refresh rate limit. The network fetch happens outside the validator lock; the key-set swap and re-lookup happen under it.
ModelContextProtocol.validate_jwt_claims — Method
validate_jwt_claims(claims::Dict{String,Any}, config::OAuthConfig, clock_skew::Int) -> AuthResultValidate JWT claims (iss, aud, exp, nbf).
ModelContextProtocol.RequestAuthContext — Type
RequestAuthContextAuthentication context attached to authenticated requests.
ModelContextProtocol.auth_error_response — Method
auth_error_response(error_code::Symbol, message::String) -> Tuple{Int,String,Dict{String,String}}Generate HTTP response for authentication errors.
Returns
- Tuple of (status_code, body, headers)
ModelContextProtocol.GitHubAuthorizationServer — Constant
GitHubAuthorizationServerPre-configured authorization server URL for GitHub OAuth.
ModelContextProtocol.WELL_KNOWN_PATH — Constant
WELL_KNOWN_PATHStandard path for Protected Resource Metadata.
ModelContextProtocol.handle_well_known_request — Method
handle_well_known_request(metadata::ProtectedResourceMetadata) -> Tuple{Int,String,Dict{String,String}}Handle a request to the .well-known/oauth-protected-resource endpoint.
Returns
Tuple of (status_code, body, headers).
ModelContextProtocol.metadata_to_json — Method
metadata_to_json(metadata::ProtectedResourceMetadata) -> StringSerialize Protected Resource Metadata to JSON for HTTP response.
ModelContextProtocol.GITHUB_API_URL — Constant
GITHUB_API_URLBase URL for GitHub API.
ModelContextProtocol.GitHubOAuthValidatorWithOrg — Type
GitHubOAuthValidatorWithOrg <: TokenValidatorWrapper validator that adds organization membership checking.
Fields
base_validator::GitHubOAuthValidator: The underlying GitHub token validatorrequired_org::Union{String,Nothing}: Required organization membership
ModelContextProtocol.check_github_org_membership — Method
check_github_org_membership(token::String, org::String) -> BoolCheck if the authenticated user is a member of the specified GitHub organization.
ModelContextProtocol.fetch_github_user — Method
fetch_github_user(token::String) -> Union{Dict{String,Any},Nothing}Fetch user information from GitHub API using an access token. Returns nothing if the token is invalid or the request fails.
Utilities
ModelContextProtocol.MCP_LOG_LEVELS — Constant
MCP_LOG_LEVELSThe log levels defined by the MCP spec (RFC 5424 severities), lowest to highest.
ModelContextProtocol.MCPLogger — Type
MCPLogger(stream::IO=stderr, level::LogLevel=Info) -> MCPLoggerCreate a new MCPLogger instance with specified stream and level.
Arguments
stream::IO=stderr: The output stream where log messages will be writtenlevel::LogLevel=Info: The minimum logging level to display
Returns
MCPLogger: A new logger instance
ModelContextProtocol.MCPLogger — Type
MCPLogger <: AbstractLoggerDefine a custom logger for MCP server that formats messages according to protocol requirements.
Once a LEGACY session is initialized, log records are delivered to the client as MCP notifications/message notifications via the server's transport (send_notification): stdio writes them to stdout alongside responses; Streamable HTTP delivers them on the originating request's SSE response stream (or the standalone notification stream when no request is being handled). Before initialization — or if transport delivery fails — records fall back to stream as JSON lines. Modern-era (2026-07-28+) requests never deliver through these ambient gates: a request that opted in via io.modelcontextprotocol/logLevel is served under a request-scoped ModernRequestLogger wrapping this logger, and every other modern request keeps the loop-armed suppression flag, so its records reach only the fallback stream.
Fields
stream::IO: Fallback output stream for log messages (used before the client initializes and when transport delivery is unavailable)min_level::LogLevel: Minimum logging level to display (mutable sologging/setLevelcan adjust it on the installed logger)message_limits::Dict{Any,Int}: Message limit settings for rate limitingtransport::Any: The server transport notifications are delivered over (Union{Nothing,Transport}; typedAnyto avoid include-order coupling)transport_active::Base.RefValue{Bool}: Gate flipped on client initialization — notifications MUST NOT be emitted to a client that has not initialized
ModelContextProtocol.ModernRequestLogger — Type
ModernRequestLogger(inner::MCPLogger, transport, route,
level::Union{String,Nothing}) <: AbstractLoggerThe logging scope of ONE modern-era (2026-07-28+) request. handle_modern_request installs it around the serve path with with_logger, which is what makes every guarantee task-inheritance-proof: child tasks a handler spawns inherit the logstate (unlike task-local storage), so their records land here too, subject to the same rules as the serving task's.
Semantics per SEP-2575: with a requested level, records at or above it (RFC-5424) are delivered as notifications/message on the ORIGINATING request's response stream — the route captured at construction, pushed via deliver_log_notification (which never closes the request's response channel under backlog pressure) on the serving transport — never on the standalone GET stream, a subscriptions/listen stream, or another server's transport. A level is only ever set when the arming site verified the current logger serves this server's transport; an identity-MISMATCHED MCPLogger (another server's) still gets a scope, but a wire-silent one (level = nothing), so child tasks cannot deliver through the foreign transport either. Without a level (no opt-in, no logging capability, or that mismatch), nothing is ever delivered. Delivery ends when closed is set (the final response is on its way) or the response channel is gone — late records are dropped, not diverted. Undelivered records fall back to the operator's inner.stream under inner's own min_level, so a debug opt-in below the operator's level never spams stderr.
Fields
inner::MCPLogger: The server's installed logger (fallback stream + operator level)transport::Any: The serving server's transportroute::Any: The request's captured notification routelevel::Union{String,Nothing}: The validated requested MCP level, ornothingfor a wire-silent scopeclosed::Base.RefValue{Bool}: Set once the request's response is under waylk::ReentrantLock: Serializes delivery against closure —close_scope!takes it to flipclosed, so a child task's in-flight delivery either completes before the final response or observesclosedand drops; the check-then-deliver window is never open across teardown
Logging.handle_message — Method
Logging.handle_message(logger::MCPLogger, level, message, _module, group, id, filepath, line; kwargs...) -> NothingFormat and output log messages according to the MCP protocol format.
Arguments
logger::MCPLogger: The MCP logger instancelevel: The log level of the messagemessage: The log message content_module: The module where the log was generatedgroup: The log groupid: The log message IDfilepath: The source file pathline: The source line numberkwargs...: Additional contextual information to include in the log
Returns
Nothing: Function writes to the logger stream but doesn't return a value
ModelContextProtocol.close_scope! — Method
close_scope!(logger::ModernRequestLogger) -> NothingEnd a request's logging scope: after this, no record is delivered on the request's response stream. Taking the delivery lock makes closure wait out any in-flight delivery, so a notification can never trail the final response.
Arguments
logger::ModernRequestLogger: The scope to close
Returns
Nothing
ModelContextProtocol.format_log_notification — Method
format_log_notification(level, message, _module, filepath, line; kwargs...) -> (String, String)Build the wire form of a log record as an MCP notifications/message.
Arguments
level: The JuliaLogLevelof the recordmessage: The log message content_module: The module where the log was generatedfilepath: The source file pathline: The source line numberkwargs...: Additional context, stringified into the metadata
Returns
Tuple{String,String}: The MCP level name and the serialized JSON-RPC notification
ModelContextProtocol.init_logging — Function
init_logging(level::LogLevel=Info) -> NothingInitialize logging for the MCP server with a custom MCP-formatted logger.
Arguments
level::LogLevel=Info: The minimum logging level to display
Returns
Nothing: Function sets the global logger but doesn't return a value
ModelContextProtocol.mcp_level_severity — Method
mcp_level_severity(level::String) -> IntThe RFC-5424 severity rank of an MCP log level (1 = debug, lowest … 8 = emergency, highest), for at-or-above comparisons.
Arguments
level::String: One ofMCP_LOG_LEVELS
Returns
Int: The 1-based rank withinMCP_LOG_LEVELS(unrecognized levels rank highest, so they never widen delivery)
ModelContextProtocol.mcp_level_to_julia — Method
mcp_level_to_julia(level::String) -> LogLevelMap an MCP/RFC-5424 log level string to the closest Julia LogLevel.
Arguments
level::String: One ofMCP_LOG_LEVELS
Returns
LogLevel:Debug,Info,Warn, orError(the four Julia standard levels)
StructTypes.names — Method
StructTypes.names(::Type{CallToolResult})Map Julia field names to their MCP wire keys: is_error → isError (the spec key — clients rely on it to detect tool errors) and structured_content → structuredContent.
StructTypes.omitempties — Method
StructTypes.omitempties(::Type{CallToolResult}) -> Tuple{Symbol,Symbol}Omit structured_content and _meta from the response when they are nothing, so tools that don't use them emit no structuredContent/_meta keys.
StructTypes.omitempties — Method
StructTypes.omitempties(::Type{ClientCapabilities}) -> Tuple{Symbol,Symbol,Symbol}Specify which fields should be omitted from JSON serialization when they are empty or null.
Arguments
::Type{ClientCapabilities}: The ClientCapabilities type
Returns
Tuple{Symbol,Symbol,Symbol}: Fields to omit when empty
StructTypes.omitempties — Method
StructTypes.omitempties(::Type{ListPromptsResult}) -> Tuple{Symbol}Specify which fields should be omitted from JSON serialization when they are empty or null.
Arguments
::Type{ListPromptsResult}: The ListPromptsResult type
Returns
Tuple{Symbol}: Fields to omit when empty