Skip to main content

Pythia

Pythia: Ask Your Dataspace

Ask your Gaia-X data space in plain language. MCP-native Python SDK for Eclipse EDC.


Pythia is a natural-language and MCP client for Gaia-X / Eclipse EDC data spaces. Instead of working with provider URLs, asset IDs, ODRL policies, and the EDC negotiation state machine directly, you ask a question in plain language and Pythia handles catalog discovery, contract negotiation, transfer, and retrieval.

from pythia import DataSpace

ds = DataSpace(
    management_url="http://consumer:29193/management",
    providers=[{"dsp": "http://provider:19194/protocol/2025-1", "id": "provider"}],
)

# Natural language query — Pythia negotiates, retrieves, and returns a readable
# Answer (a synthesized table + provenance). Pass raw=True for the raw asset bytes.
answer = await ds.ask("CO2 emissions data for German automotive suppliers 2023")
print(answer.to_markdown())

It also ships as an MCP server, exposing data-space queries as tools for Claude, GPT, or any MCP-compatible agent.

Components

Layer Component
1 — Core client Async httpx EDC client, full DSP state machine, typed errors, no RabbitMQ
2 — NL interface ds.ask() — parallel catalog fan-out + offline granite-embedding-97m-multilingual-r2 ranking + auto-negotiate; returns a readable Answer by default (synthesized table on success, or an explained refusal in Answer.note), raw=True for bytes
3 — MCP server pythia-mcp — wraps ds.ask() as MCP tools for Claude / GPT / any agent

Install

pip install 'pythia-edc[all]'

Running the demo

The repo ships a self-contained demo stack driven by a single ./demo entrypoint.

./demo up                          # start the stack
./demo ask "CO2 emissions for German automotive suppliers 2023"
./demo repl                        # interactive query loop
./demo down                        # stop the stack

By default ./demo up runs everything locally: provider + consumer EDC connectors, a mock data server, and provider seeding.

Config profiles

Any setting can live in a profile file instead of inline env vars. ./demo loads demo.env by default and exports every assignment to both the stack scripts and the Python client. Copy the example to get started:

cp demo.env.example demo.env       # edit, then ./demo up

Keep several named profiles and select one per run with ENV_FILE:

ENV_FILE=demo.consumer.env ./demo up

Local consumer, remote providers

To run only the consumer locally and talk to providers that run on separate servers, set CONSUMER_ONLY=1 (skips the local provider, mock server, and seeding) and point PYTHIA_PROVIDERS at the remote DSP endpoints. See demo.env.example for the full template, including the TLS variables (PYTHIA_CA_BUNDLE, PYTHIA_CLIENT_CERT/KEY) for talking to remote providers.

CONSUMER_ONLY=1 \
PYTHIA_PROVIDERS='[{"dsp":"https://provider1.example/protocol/2025-1","id":"rheinmobil"}]' \
./demo up

Usage

# Low-level
catalog = await ds.catalog.query(provider_dsp="...", provider_id="...")
agreement_id = await ds.negotiate(provider_dsp="...", provider_id="...",
                                  offer_id=offer.id, asset_id=asset.id)
data = await ds.fetch(provider_dsp="...", provider_id="...",
                      agreement_id=agreement_id, asset_id=asset.id)

# Natural language — returns a readable Answer (table + provenance)
answer = await ds.ask("quarterly SVHC substance reports from EU chemical suppliers")
print(answer.to_markdown())

# ...or the raw asset bytes, for the developer/agent path
raw = await ds.ask("quarterly SVHC substance reports", raw=True)

Command line

Installing the package puts a pythia command on your PATH, so you can query a data space from anywhere:

# Install globally in an isolated environment (uv) — or use pipx
uv tool install 'pythia-edc[all]'

# Point it at your consumer connector + providers, then ask
export PYTHIA_MANAGEMENT_URL="http://localhost:29193/management"
export PYTHIA_PROVIDERS='[{"dsp": "http://localhost:19194/protocol/2025-1", "id": "provider"}]'

pythia ask "CO2 emissions for German automotive suppliers 2023"
pythia ask "quarterly SVHC reports" --verify-trust --json

# Inspect what a data space offers, without negotiating (mirrors the MCP
# browse_catalog tool). Lists assets across all configured providers.
pythia catalog
pythia catalog --provider rheinmobil https://provider1.example/protocol/2025-1 --json

Connection settings are read from PYTHIA_* environment variables (see pythia.config.ConnectorConfig); --management-url and --provider ID DSP (repeatable) override them per invocation. Run pythia ask --help for all options.

Provider responses are streamed and capped at 100 MiB by default (a memory-DoS guard against a hostile connector); override with PYTHIA_MAX_RESPONSE_BYTES or the max_response_bytes kwarg on DataSpace.

The repo's ./demo ask is the zero-config local playground; pythia ask is the same query path pointed at real connectors you configure.

MCP server

export PYTHIA_MANAGEMENT_URL="http://localhost:29193/management"
export PYTHIA_PROVIDERS='[{"dsp": "http://localhost:19194/protocol/2025-1", "id": "provider"}]'
pythia-mcp

Gaia-X standards

Standard Usage
DSP dataspace-protocol-http:2025-1 Full state machine: catalog → negotiate → transfer → EDR
DCAT Catalog parsing, asset/offer extraction
ODRL Policy offer construction with correct context
MCP (Model Context Protocol) AI agent integration (pythia-mcp server)
Verifiable Credentials + SHACL Trust slice: verify a provider VC (structure + signature) and validate the offer + ODRL policy against a SHACL shape before negotiating

Provider VC verification

When verify_trust=True and a credential_source is supplied, Pythia verifies each provider's Verifiable Credential fully offline before validating its offer:

  • structural validation (required @context / type / id / issuer fields, SHACL shape)
  • validity-window check (validFrom / expiry)
  • Ed25519 JsonWebSignature2020 detached-JWS signature verification via did:key
  • issuer ↔ signing-key binding (the verifying key must belong to the credential issuer)
  • an optional issuer trust-list of allowed issuer DIDs
from pythia import DataSpace, StaticCredentialSource

ds.ask("CO2 emissions from German automotive suppliers 2023",
       verify_trust=True,
       credential_source=StaticCredentialSource({"provider": provider_vc}),
       trust_list={"did:key:z6Mk..."})

Rejections surface as structured CredentialError.failures, rendered into prose by the Explainer (e.g. "the credential has expired", "the credential issuer is not trusted").

In the demo, trust verification is on by default: ./demo ask "..." verifies each provider's VC and SHACL-validates its offer before negotiating. The demo mints VCs from a fixed demo CA for the trusted providers, while DonauTech is intentionally untrusted — its VC is signed by an issuer not on the consumer's trust-list, so it is rejected (UntrustedIssuer) and the query falls through to a trusted provider. Disable the gate with ./demo ask --no-verify-trust "...". (The library default of verify_trust is unchanged — off — so non-demo callers opt in explicitly as shown above.)

Roadmap: full GXDCH / Notary online credential verification, and resolving did:web issuer DID-documents (the current crypto path effectively trusts did:key issuers, since the verifying key must equal the issuer); provider auto-discovery (the Meta Registry is a trust-profile source, not a connector directory, so endpoint discovery needs an EDC FederatedCatalog or a self-description convention).

Prerequisites

  • Python 3.13+, running EDC consumer + provider connectors
  • sentence-transformers for ds.ask() ranking (offline, ibm-granite/granite-embedding-97m-multilingual-r2, ~130MB, multilingual)
  • A local LM Studio server for the default ds.ask() answer (the synthesized table) and the optional LLMExplainer. LM Studio exposes an OpenAI-compatible API at http://localhost:1234/v1 (Developer → Start Server); load a model and Pythia will use it. Override the endpoint/model with PYTHIA_LLM_BASE_URL / PYTHIA_LLM_MODEL. Without it, ds.ask() still ranks, negotiates, and fetches — pass raw=True for the asset bytes, or the default Answer carries a note explaining the synthesizer was unreachable.

The local end-to-end demo additionally needs Docker and a checkout of the Eclipse EDC Samples (point EDC_SAMPLES_DIR at it).

Contributing

Contributions are welcome — see CONTRIBUTING.md for setup and the checks to run.

License

MIT © Pareo

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pythia_edc-0.3.0.tar.gz (67.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pythia_edc-0.3.0-py3-none-any.whl (45.3 kB view details)

Uploaded Python 3

File details

Details for the file pythia_edc-0.3.0.tar.gz.

File metadata

  • Download URL: pythia_edc-0.3.0.tar.gz
  • Upload date:
  • Size: 67.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pythia_edc-0.3.0.tar.gz
Algorithm Hash digest
SHA256 5e3c6e84aedb378127d17770cf17e9b6ec007c0db6af598766c0f62c6d7a29b6
MD5 0acfa809428516653e2255dec8715553
BLAKE2b-256 bd33b18d13cf6fb7630efe3ba3334c3c8c610d3fad5910ff48056574496f5678

See more details on using hashes here.

Provenance

The following attestation bundles were made for pythia_edc-0.3.0.tar.gz:

Publisher: publish.yml on Pareo-AI/pythia-edc

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file pythia_edc-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: pythia_edc-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 45.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for pythia_edc-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 baaad02e642495a584674ff066609c8e264e5692f502c8168b054c1bc2cd98c4
MD5 0c23cec2cbe7e7792a5c35b9d9974b9e
BLAKE2b-256 9321a0823f087d029e0e17b1f192eb3eb185249b21a61b728f979f19784cbbf0

See more details on using hashes here.

Provenance

The following attestation bundles were made for pythia_edc-0.3.0-py3-none-any.whl:

Publisher: publish.yml on Pareo-AI/pythia-edc

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 files

0.2.0

2 files

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