Skip to main content

HttpCodeExecutor

Struct HttpCodeExecutor 

Source
pub struct HttpCodeExecutor { /* private fields */ }
Expand description

Low-level HTTP executor bridging the toolkit’s outbound HttpAuthProvider to pmcp-code-mode’s HttpExecutor trait.

This is the OpenAPI analog of SqlCodeExecutor, but at a DIFFERENT layer: it impls the LOW-LEVEL pmcp_code_mode::HttpExecutor (execute_request(method, path, body)), NOT the high-level CodeExecutor. It is wrapped by a JsCodeExecutor for the Code Mode path (the JsCodeExecutor<HttpCodeExecutor>: CodeExecutor blanket impl) and is called directly by script tools (Plan 05). The single-call synthesizer (Plan 03) does NOT use this path — it calls HttpConnector::execute directly.

§Per-request passthrough token (H1)

The inbound_token field carries the per-request MCP client token captured by the binary (Plan 06) into [AuthContext]. It is passed to HttpAuthProvider::apply so an OAuthPassthroughAuth provider forwards it to the backend; static providers ignore it (proven in Plan 01). Because Code Mode reuses ONE executor instance across requests, the binary produces a per-request clone carrying the captured token via HttpCodeExecutor::with_inbound_token.

§Redaction (Pitfall 5 / T-90-04-01)

Auth/transport failures are mapped to ExecutionError::RuntimeError whose message names the operation / status only — it NEVER echoes the request URL or the Authorization token.

§Feature gate (H2)

Gated under openapi-code-mode (the Plan 90-01 umbrella that forwards pmcp-code-mode/js-runtime). The bare code-mode feature does NOT bring HttpExecutor into scope, so this type cannot be gated on all(feature = "http", feature = "code-mode").

Implementations§

Source§

impl HttpCodeExecutor

Source

pub fn new( client: Client, base_url: String, auth: Arc<dyn HttpAuthProvider>, ) -> Self

Construct an executor over client + base_url, authenticating outgoing requests via auth. The per-request inbound_token starts None; the binary attaches it per request with HttpCodeExecutor::with_inbound_token.

Source

pub fn with_tool_label(self, tool: impl AsRef<str>) -> Self

Label this executor with the MCP tool it serves, so an E1 policy is told which tools/call an outbound request came from (Phase 128).

Attach it where a PER-TOOL executor is minted — ScriptToolHandler::new for a script tool, code_mode_http_tools_from_executor for execute_code. On the Code Mode surface one tools/call may issue many outbound requests and they all carry this same label.

Source

pub fn tool_label(&self) -> &str

The MCP tool this executor serves, or "" when it carries no label (a caller driving the executor directly, with no tool to name).

Source

pub fn with_call_id(self, call_id: impl AsRef<str>) -> Self

Stamp the per-tools/call id onto every policy request this executor makes, see crate::policy::OutboundRequest::call_id.

request_executor_from_extra calls this once per tools/call, so an embedder normally never does. It is public for an embedder that derives its own per-call executor and wants its requests grouped the same way.

Source

pub fn call_id(&self) -> &str

The id of the tools/call this executor serves, or "" on a base executor that no call has derived from (nothing to group by).

Source

pub fn with_request_policy(self, policy: Arc<dyn RequestPolicy>) -> Self

Attach the E1 crate::policy::RequestPolicy consulted before every outbound request this executor makes (Phase 128).

Cheap clone-with-builder, the same shape as with_inbound_token.

§Call it BEFORE the executor fans out

Both HTTP surfaces run on ONE executor (D-02) — script tools take a clone and Code Mode takes the original — so a clone taken before this builder runs is permanently ungoverned. The same constraint with_schema documents, for the same reason.

Source

pub fn has_request_policy(&self) -> bool

Whether this executor consults an E1 policy before sending.

Public for the same reason has_schema is: the wiring lives in a different crate, so a registered-but-unreached policy must be observable from outside rather than only from a #[cfg(test)] accessor.

Source

pub fn with_schema(self, schema: Arc<OpenApiSchema>) -> Self

Attach the operator’s parsed OpenAPI document, so a path placeholder can be narrowed by what the spec DECLARES for it (Phase 128 D4(b)).

Cheap clone-with-builder, the same shape as with_inbound_token: the Arc is shared with the api_schema resource rather than the document being duplicated.

§Call it BEFORE the executor fans out

Both HTTP surfaces run on ONE executor (D-02) — script tools take a clone and Code Mode takes the original. A clone taken before this builder runs is permanently unnarrowed, so the call has to precede both fan-out sites. The production wiring is pmcp-openapi-server’s build_server, the only place the executor and the parsed spec are both in scope.

Source

pub fn with_inbound_token(self, token: Option<String>) -> Self

Cheap clone-with-token builder (H1): the binary calls this PER REQUEST to attach the captured inbound MCP token so an oauth_passthrough provider forwards it. Static providers ignore the token, so calling this on a static-auth executor is harmless.

Single-call tools (Plan 03) don’t use this path; the per-request token flows through Code Mode + script tools only.

Source

pub fn has_schema(&self) -> bool

Whether this executor carries an OpenAPI document, and therefore whether a path placeholder can be narrowed by a spec DECLARATION (Phase 128 D4(b)).

false never means “unchecked”: a spec-less executor still applies the unconditional character floor and the always-on length cap to every placeholder value. It means only that no ADDITIONAL declared narrowing is available.

Public, and deliberately so. T-128-36c is the risk that with_schema gets wired to a #[cfg(test)] helper — or applied after the executor has already fanned out — leaving the production binary unnarrowed while every test passes. The wiring lives in a DIFFERENT crate (pmcp-openapi-server’s build_server), so a #[cfg(test)] accessor could not prove it from there. This is a read-only boolean over a private field; it exposes nothing about the document.

Trait Implementations§

Source§

impl Clone for HttpCodeExecutor

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl HttpExecutor for HttpCodeExecutor

Source§

fn placeholder_rules( &self, method: &str, path_template: &str, param: &str, ) -> PlaceholderRules<'_>

Narrow a layer-2 {param} value by what the carried OpenAPI document DECLARES for it (Phase 128 D4(b)).

Delegates to the private spec_placeholder_rules helper in this module, whose rustdoc states exactly what a schema/operation/parameter MISS costs — the floor and the cap are retained, the spec’s narrowing is lost — and what bounds that loss. Named in plain backticks rather than as an intra-doc link because this method is public and the helper is private, which rustdoc (correctly) warns about.

Source§

fn execute_request<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, method: &'life1 str, path: ResolvedPath<'life2>, body: Option<Value>, ) -> Pin<Box<dyn Future<Output = Result<Value, ExecutionError>> + Send + 'async_trait>>
where Self: 'async_trait, 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait,

Execute an HTTP request. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> FromRef<T> for T
where T: Clone,

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

Source§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> Send for T
where T: ?Sized,

Source§

impl<T> Sync for T
where T: ?Sized,

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more