Skip to main content

xippios-mcp

The self-hosted MCP host of the xippios SDK family. It serves the MCP tools of the family's packages from one process, by endpoint and group: an endpoint mounts a package's own server, read or write, and a group combines several packages' tools on one endpoint, never read and write tools together. It runs on stdio locally and on streamable HTTP on a server, each endpoint with its own auth, a bearer token by default; the secrets stay in the environment, never in the config file.

xippios-mcp --config <path> checks a config, builds every endpoint's server and lists the endpoints; --stdio <endpoint> serves one endpoint on stdio, and --http serves every endpoint over streamable HTTP, each with its bearer (see Serving). A Docker image, built from this repository, serves them from a container (see Docker).

Install

uv add "xippios-mcp[all]"          # the host with every package below
uv add "xippios-mcp[usda-nass]"    # or one extra per package you serve

Packages

Each package is an extra with a lower bound only, so the host installs every package at its latest release.

Extra Distribution Lower bound Servers Tools
cashctrl xippios-cashctrl >=0.3.0 read and write 24 read, 11 write
comtrade xippios-comtrade >=0.2.0 read 19
eurostat xippios-eurostat >=0.2.0 read 13
faostat xippios-faostat >=0.1.0 read 7
usda-esmis xippios-usda-esmis >=0.2.0 read 9
usda-esr xippios-usda-esr >=0.2.0 read 10
usda-gats xippios-usda-gats >=0.2.0 read 20
usda-nass xippios-usda-nass >=0.2.0 read 16
usda-psd xippios-usda-psd >=0.3.0 read 12

The tools are each package's tasks.__all__ (tasks_write.__all__ for a write server) less its BULK_TASKS, which are Python-only, counted at the version of the lower bound; a later release may add tools. all installs the nine. xippios-usda-wasde joins later: its 0.1.1 needs xippios-usda-esmis below 0.2.

The ceilings of usda-nass and usda-gats

--split-years of xippios-usda-nass-mcp and --series-months of xippios-usda-gats-mcp are options of those packages' own entry points, which the host does not run. The host therefore serves the ceilings the packages keep in Python: a split usda_nass_get_data spans up to 20 years, at up to two keyed calls a year (the entry point's default is 5 years), and usda_gats_get_census_export_series, usda_gats_get_census_import_series and usda_gats_get_census_reexport_series span up to 60 months, at one call a month (the entry point's default is 24 months). An operator who wants fewer calls per tool call leaves those tools out with an endpoint's exclude list (see Configuration).

Configuration

The host reads one TOML file that names its endpoints. Each [endpoints.<name>] table is one endpoint, which the HTTP transport serves at /<name>/mcp:

[endpoints.agriculture]                        # served at /agriculture/mcp
packages = ["usda-nass", "usda-psd", "comtrade"]
exclude = { usda-nass = ["get_counts"] }       # or include = { ... }; exact task names
auth = "bearer"                                # the default; or "none"
token_env = "XIPPIOS_MCP_AGRICULTURE_TOKEN"    # a name ending in _TOKEN, never a value
allow_remote = false                           # the default

[endpoints.accounting-write]
packages = ["cashctrl:write"]
auth = "none"
  • An endpoint that names one package and no list serves that package's own server, as the package builds it: xippios.<package>.mcp.server, or mcp_write.server for <slug>:write, with its instructions and result caps.
  • A group, several packages, or an endpoint with an include or exclude list is a server the host builds, named xippios-<endpoint>: each package's tools under their own names (usda_nass_get_data), with the package's result caps for the tools it keeps.
  • Read and write never mix: an endpoint's packages are all <slug>:write or none, and the host refuses a group that mixes them.
  • include and exclude are keyed by package slug and name exact task names, a task function's __name__ (get_counts, not usda_nass_get_counts); a package takes one of the two, and an empty list is refused. A name that is no tool of the package is refused, a task in the package's BULK_TASKS among them, since a bulk task is Python-only and no tool.
  • auth is "bearer" by default, or "none". With the bearer, token_env names the environment variable that holds the token, a name ending in _TOKEN (XIPPIOS_MCP_<ENDPOINT>_TOKEN), and the token itself stays in the environment, never in the file. The host reads the variable once, when --http starts, and never on stdio or when it lists. allow_remote is false by default; it lets an auth = "none" write endpoint beyond loopback (see The loopback rule).
  • An optional [http] table names the Host and Origin values the HTTP transport accepts behind a reverse proxy (see Behind a reverse proxy).

Check a config before serving it:

xippios-mcp --config host.toml

It loads the file, builds every endpoint and prints one line per endpoint; for docs/host.example.toml, the sample above, with the packages at the lower bounds:

agriculture: read, 46 tools of usda-nass, usda-psd, comtrade
accounting-write: write, 11 tools of cashctrl

A key, package or task the host refuses stops it with exit status 2 and a message that names the file, the endpoint and the key. The list runs neither the mounted-once check nor the loopback check of Serving, which need --http and its --host.

A server the host builds carries none of the packages' own instructions: its instructions are one sentence naming its packages and their tool counts. No endpoint takes a package's command-line options, such as cashctrl's --org lock or the ceilings above, since the host runs no package's entry point. The package contract of the next template release gives the host what it needs to carry them, in its 0.2.0.

Serving

stdio

xippios-mcp --config host.toml --stdio agriculture

serves the one endpoint agriculture on stdio, for an MCP client that starts the host as its own process. stdio has no auth: the host reads no token variable, and an endpoint's auth, token_env and allow_remote apply to HTTP only. In Claude Code:

claude mcp add agriculture -- xippios-mcp --config host.toml --stdio agriculture

with the config's absolute path in place of host.toml when Claude Code runs in another directory.

Streamable HTTP

xippios-mcp --config host.toml --http --host 127.0.0.1 --port 8000

serves every endpoint of the config from one process, each at http://127.0.0.1:8000/<name>/mcp: http://127.0.0.1:8000/agriculture/mcp for the sample. --host defaults to 127.0.0.1 and --port to 8000; both need --http, and --http and --stdio exclude each other. Before it serves, the host reads each bearer endpoint's token and applies the checks below; a refusal exits with status 2 and serves nothing. A package's own server serves one HTTP endpoint: two endpoints that each name usda-nass alone are refused, and an include or exclude list on one of them makes its server one the host builds.

The bearer

An endpoint with auth = "bearer" answers a request without the token with 401 and WWW-Authenticate: Bearer realm="xippios-mcp", and one with a wrong token with error="invalid_token" added; such a request never reaches the endpoint. The token is the value of the variable token_env names, read once when --http starts: an unset or empty variable stops the host with exit status 2, and so does a value with leading or trailing whitespace, which no token a client sends can match. The host keeps the token's SHA-256 digest only, compares in constant time, and never logs the token or the Authorization header. A random token will do, openssl rand -hex 32 for instance, set in the environment of the host and of the client.

In Claude Code:

claude mcp add --transport http agriculture http://127.0.0.1:8000/agriculture/mcp \
  --header 'Authorization: Bearer ${XIPPIOS_MCP_AGRICULTURE_TOKEN}'

In single quotes the shell passes ${XIPPIOS_MCP_AGRICULTURE_TOKEN} on as written, and Claude Code expands it from its own environment when it connects, so the token stays out of Claude Code's config; in double quotes the shell would write the token itself into the config. Claude Code reads some well-known credential variables as empty in a remote server's headers (its own, a cloud provider's, others such as NPM_TOKEN); a name of the operator's own, such as XIPPIOS_MCP_AGRICULTURE_TOKEN, is outside that set and expands as written. When a token does not arrive, claude --debug-file <file> logs never expanded toward a remote server for a covered name.

The bearer does not serve claude.ai. claude.ai signs in with OAuth: it starts on a 401 that names a resource_metadata document, and it needs an OAuth authorization server. The host advertises no resource_metadata and is no authorization server, so claude.ai needs one in front of the host, which 0.1.0 leaves out (ADR-0026, decision 10).

The loopback rule

An endpoint with auth = "none" that serves a write server, cashctrl:write for instance, carries no authentication, so --http serves it on a loopback --host only, 127.0.0.1, localhost or ::1, as a package's own entry point keeps its write server (ADR-0014, decision 9). On another --host the host refuses to start unless the endpoint sets allow_remote = true, and then a gateway in front of it has to authenticate. A read endpoint with auth = "none", and every bearer endpoint, is served on any host.

A read server that its package holds to loopback, as sdk-google-mail holds its own, is not held there by the host's 0.1.0: the packages' loopback-only option is planned for xippios-core's next minor, for the host to read from its own 0.2.0 on. None of the nine packages 0.1.0 serves holds a read server to loopback, so the case cannot arise before a package that does joins, sdk-google-mail once it has a release and an extra. Until the host reads the option, keep an auth = "none" endpoint of such a package on a loopback --host, or give it the bearer.

Behind a reverse proxy

On a loopback --host the mcp SDK checks the Host and Origin headers itself and accepts loopback values only, which keeps a web page from reaching the host through DNS rebinding. Beyond loopback it checks neither, unless the config names what to accept:

[http]
allowed_hosts = ["mcp.example.com"]            # the Host values the proxy forwards
allowed_origins = ["https://mcp.example.com"]  # browser origins, if any

The lists replace the SDK's loopback default for every endpoint: a request whose Host is not listed gets 421, and one with an Origin that is not listed gets 403; a request without Origin passes. "<host>:*" accepts any port, so add "127.0.0.1:*" to keep clients that connect directly. Both keys are optional, but allowed_origins needs allowed_hosts. Without the table, a host bound beyond loopback gets no Host check.

Docker

The repository builds an image of the host with every package of all, at the versions uv.lock pins, the set the tests run against. 0.1.0 publishes no image to a registry: build it from a checkout.

docker build -t xippios-mcp .

The image runs xippios-mcp --config /etc/xippios-mcp/host.toml --http --host 0.0.0.0 --port 8000 as the non-root user xippios (uid 10001), and holds no config, key or token. The operator mounts the config, a file that user can read, and passes every token by its variable's name, so the value comes from the operator's environment and stays out of the command line. For a config with one bearer endpoint:

[endpoints.agriculture]
packages = ["usda-nass", "usda-psd", "comtrade"]
auth = "bearer"
token_env = "XIPPIOS_MCP_AGRICULTURE_TOKEN"
docker run --rm -p 8000:8000 \
  -v "$PWD/host.toml:/etc/xippios-mcp/host.toml:ro" \
  -e XIPPIOS_MCP_AGRICULTURE_TOKEN \
  xippios-mcp

serves it at http://127.0.0.1:8000/agriculture/mcp. The variables the packages read themselves, their keys among them, are passed the same way, by name; each package's README names its own. Arguments after the image name replace the image's own, so

docker run --rm -v "$PWD/host.toml:/etc/xippios-mcp/host.toml:ro" xippios-mcp \
  --config /etc/xippios-mcp/host.toml

checks the mounted config and lists its endpoints without serving them.

Inside the container the host binds 0.0.0.0, beyond loopback, so every endpoint is remote, whichever interface -p publishes the port on: give every endpoint the bearer. An auth = "none" write endpoint is refused there unless it sets allow_remote = true (see The loopback rule), and then nothing authenticates it but a gateway in front; prefer the bearer. Beyond loopback the mcp SDK checks no Host or Origin header, so behind a reverse proxy the config's [http] table names the values to accept (see Behind a reverse proxy).

Licence

Apache-2.0. See LICENSE.

Metadata

Release files for xippios-mcp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for xippios-mcp 0.1.0
File Size Uploaded Provenance Actions
xippios_mcp-0.1.0.tar.gz 27.1 kB With provenance Details for xippios_mcp-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for xippios-mcp 0.1.0
File Interpreter ABI Platform Actions
xippios_mcp-0.1.0-py3-none-any.whl Python 3 none any Details for xippios_mcp-0.1.0-py3-none-any.whl

Total release size: 56.1 kB

Release files / xippios_mcp-0.1.0.tar.gz

Download URL xippios_mcp-0.1.0.tar.gz
Size 27.1 kB
Tags Source
SHA-256 checksum
How to use checksums
3b22a06a20b9a49ff2238a2557644a1491f81c7a10a1d33e44d7d234344bffc9
BLAKE2b-256 checksum
How to use checksums
c99086246565afdb26fe9d1a89136a0f271ccd491cc126404bf2240d2a0ea340
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Release files / xippios_mcp-0.1.0-py3-none-any.whl

Download URL xippios_mcp-0.1.0-py3-none-any.whl
Size 29.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7b2bca41ea5519d50e07115ac24998cc23eea964dac027b0a013dc8f69f480c9
BLAKE2b-256 checksum
How to use checksums
b837561ea68d38b95aba831d89c98c29521c6f31052e032dbde022ebaaa9c650
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

Security for xippios-mcp 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for xippios_mcp-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 29, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page