This guide explains the operator-visible architecture of MCP Passthrough v0.29.3: which component handles a request, whose account pays, and where data is processed. Start with Setup for installation and Providers for configuration.
Roles
| Role | Responsibility |
|---|---|
| MCP client | Connects to a plugin endpoint using the customer bearer key issued by that node. Sends model requests and reads results and usage receipts. |
| Serving node | The eIOU node the client connects to. Authenticates the customer, enforces limits, chooses a provider and maintains its customer billing ledger. It is also the routing node when automatic routing is enabled. |
| Provider node / seller | Another eIOU node that advertises inference and serves it through its own plugin. It admits the buying node and accounts for that buyer’s usage. |
| Upstream model service | The API or runtime that executes inference. It can be an online model API or a runtime on infrastructure operated by the provider. |
| Discovery/payment contact | An eIOU contact involved in learning offers or routing a payment. It does not automatically become an inference endpoint. |
A serving node may call an upstream API directly, or buy from a provider node that calls its upstream service. One node can serve customers and offer its configured models at the same time.
Each node serving, routing or advertising inference needs its own plugin installation. A billing wallet or payment-only relay does not need the plugin. Nodes hosted by the eIOU team use remote inference; those hosted servers do not run local models or Ollama sidecars. Self-hosted operators may additionally run local runtimes on their own infrastructure.
Request paths
Direct configured provider:
MCP client → serving node → configured upstream API or local runtime
Network provider:
MCP client → serving/routing node → provider node → upstream API or local runtime
The response returns along the selected inference path. The client keeps its key for the serving node. It does not need the provider node’s credential or the upstream model service’s API token.
The network path is selected using offers learned through contacts, but the serving node contacts the selected seller directly for inference. A longer discovery horizon or a payment routed through several contacts does not imply that each contact receives the prompt.
What happens on a model call
- The plugin validates the bearer key, session and applicable admission rules. In pilot mode, the key must remain bound to an accepted contact.
- The service creates a route plan from the requested model and the operator’s routing policy.
- It checks customer funding and quotas, estimates the reservation needed for input and permitted output, and reserves the customer charge before inference.
- For a network candidate, it checks the node-managed seller credential and funding. A missing credential must be prepared by warming or scheduled maintenance; the interactive request does not mint it.
- The selected provider receives the request. On completion, the plugin reconciles the reservation against metered usage and records a billing receipt.
Token counts may be estimated when the upstream service does not provide them. A reserved amount can therefore differ from the final charge. Streaming interruption after output has started can still result in a partial usage charge; see the API reference for the returned fields and errors.
Two separate funding relationships
Customer to serving node
The customer’s bearer key has a plugin balance at the serving node. Eligible incoming eIOU payments can top up that balance. A contact-bound key may also use the credit available to its accepted billing contact, subject to the host’s credit checks. Contact credit is shared across that contact’s keys; minting another key does not create another independent credit allowance.
Being the serving node’s operator does not bypass this relationship. In default pilot mode, a client still needs a key tied to an accepted billing contact. A node cannot be its own contact.
Serving node to provider node
For network inference, the serving node holds a separate seller-issued credential and balance at the provider node. The credential manager can send eIOU funding payments through the host wallet under the routing limits. The host needs an accepted payment/credit route capable of making those payments.
A positive customer balance at the serving node is not a balance at the seller. Seller funding may be asynchronous, so the first request can encounter an unready route even though the customer is funded. Warm the best sellers in the GUI or the corresponding CLI operation prepares access before the call.
The seller separately pays or supplies its upstream inference service. Configuring an online model API generally means the seller uses its own upstream account and token; the customer’s eIOU key is not that API credential.
Discovery, admission and routing
Discovery is separate from access
The directory exchanges enabled model offers with accepted contacts. Learned offers carry freshness and discovery-distance information; routing filters them by model, currency and operator policy. Directory sync is scheduled every ten minutes, with a manual operation available in the CLI.
Finding a seller through a contact does not establish that the seller accepts the buyer. In pilot mode, the buying node must prove an identity that the seller itself recognizes as an accepted contact to obtain a new contact-bound credential. An eIOU payment route alone does not satisfy that admission check.
Signed contact admission
Default pilot mode allows operator-minted keys for accepted contacts. Peers can also prove an accepted node identity using a signed contact assertion for directory access or /request-key.
Assertions are bound to the receiving node, include a timestamp and nonce, and are verified using host identity/contact services. This provides proof of contact identity during admission. Subsequent inference uses the seller-issued bearer credential; this release does not replace every inference request with a node signature.
open mode deliberately enables unverified key signup. Learned peer addresses are still withheld from unverified directory callers; an open caller can obtain the node’s own advertised catalog. Revocation, expiry and current contact acceptance remain relevant to bound credentials.
Routing controls and fallback
The default mode is manual, which uses the active configured provider. auto can choose configured providers and network offers; network_only considers network offers only. In routing terminology, a “local” candidate means a provider configured on this node. It can be an online API, rather than a model running on the same server.
Operators set funding limits, request-price ceilings, permitted remote use, candidate counts and ranking policy. Cheapest advertised ranks estimated advertised inference charges adjusted for recent route failures, not a guaranteed total including payment-route fees. The client may narrow applicable routing limits but cannot enable routing or raise the operator’s spending ceilings.
Eligible failures before output can cause the next candidate to be tried. The plugin does not retry the same request on another route after output has been delivered. A provider may nevertheless have received the prompt before failing; fallback can therefore expose it to more than one provider.
Host and plugin boundary
The plugin runs through the host’s sandbox dispatcher. Its panel, CLI, operator REST API, public routes, transaction hooks and scheduled jobs are declared in plugin.json and handled by the dispatcher.
The host provides node identity, accepted contacts, credit state, wallet sends/refunds, resources and logging through declared service calls. The plugin has its own database user and tables. Plugin enablement, permission approval and exposing Public routes are host responsibilities; installing the ZIP alone does not establish provider access or customer funding.
| Permission | Operational purpose |
|---|---|
wallet_refund_return_to_sender |
Refund eligible received top-up payments through the host’s restricted refund service. |
host_resources_read |
Read host resource information for capacity checks and runtime information. |
contact_address_book_enumerate |
Learn accepted contacts for discovery and admission. |
wallet_outbound_send |
Send provider funding payments and supported deal payments. |
node_identity_assert |
Ask the host to sign plugin-specific contact assertions. |
contact_credit_read |
Check available contact credit for customer billing. |
The wallet GUI uses the host’s authenticated action/CSRF handling. Public MCP requests use plugin bearer keys. Operator REST access follows the host API authentication mechanism; a customer key does not become a wallet administrator key. See API.
Storage, secrets and privacy boundaries
Durable plugin state resides in MySQL tables prefixed plugin_mcp_passthrough_. Current operation requires that database; the old state.json format is a migration source, not the active storage backend.
| Data | Stored or processed where |
|---|---|
| Customer keys | The issuing node stores a password hash and lookup value, binding, balance, currency, expiry and origin settings. The plaintext key is returned when minted. |
| Upstream API tokens and managed seller credentials | The node stores recoverable encrypted credentials using the host-provided master key. They must be decrypted when making authenticated requests. |
| Usage and route attempts | The node stores billing/routing metadata such as model, provider, token counts, costs, timestamps, attempts and errors. These tables are not a chat transcript. |
| Explicit deal jobs | The buyer’s job record can persist prompt text for deferred/resumed execution. The GUI’s Deals table does not display that field. |
| Directory and top-ups | The node stores discovered seller offers and payment/accounting records needed for operation. |
| MCP sessions and notifications | The node stores protocol/session state and operational events. These have their own cleanup behavior, rather than a single retention period for all plugin data. |
The serving node, selected provider node and any upstream model service on the chosen path process prompts and outputs. Their operators, hosting administrators, proxies, monitoring systems or backups may also have access according to their configuration. Encryption of stored credentials does not prevent a host administrator with access to the running service and its key material from accessing those credentials.
The ordinary inference usage table does not store prompt or response text. That does not establish that all prompts are unlogged: explicit deal jobs can retain prompts, and upstream services and surrounding infrastructure have their own logging and retention policies. Operators need to state those policies for their deployment.
Payment/discovery intermediaries receive the information needed for their roles; they are not deliberately given the model conversation by this plugin’s inference path. Tor transport reduces some network exposure but does not eliminate traffic-correlation risks or replace endpoint trust.
Removing local plugin data does not remove a seller’s records, upstream logs or external backups. For recovery, preserve the matching host key material with the database backup: restoring encrypted credential rows without the corresponding key does not restore usable provider access.
Implementation map
| Component | Source |
|---|---|
| Request execution, reservation and settlement | Service.php |
| Routing selection and policy | FederatedRouter.php, RoutingPolicy.php |
| Managed seller access and funding | FederatedCredentialManager.php |
| Admission and signed proof | PeerAdmission.php, ContactAssertion.php |
| Database state and credential protection | State.php, TokenVault.php |
| Provider adapters | ProviderFactory.php |
Return to the documentation introduction, or continue with GUI, CLI and API references.
Source: docs/ARCHITECTURE.md at revision 07476eedee57.