Metadata-Version: 2.5
Name: trustgate-sdk
Version: 0.2.0
Summary: TrustGate SDK - governed tools and models for agents, over the MCP and LLM planes of a TrustGate gateway.
Project-URL: Homepage, https://github.com/NeuralTrust/trustgate-sdk
Project-URL: Documentation, https://docs.neuraltrust.ai/sdks/trustgate/overview
Project-URL: Repository, https://github.com/NeuralTrust/trustgate-sdk
Project-URL: Issues, https://github.com/NeuralTrust/trustgate-sdk/issues
Author: NeuralTrust
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: agents,gateway,llm,mcp,model-context-protocol,neuraltrust,trustgate
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Classifier: Typing :: Typed
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.15; extra == 'dev'
Description-Content-Type: text/markdown

# trustgate-sdk

[![PyPI](https://img.shields.io/pypi/v/trustgate-sdk)](https://pypi.org/project/trustgate-sdk/)
[Documentation](https://docs.neuraltrust.ai/sdks/trustgate/overview) · [TypeScript package](https://www.npmjs.com/package/@neuraltrust/trustgate) · [GitHub](https://github.com/NeuralTrust/trustgate-sdk)

The TrustGate SDK for Python. 3.10+, standard library only.

```bash
pip install trustgate-sdk
```

## Setup

```python
from trustgate import TrustGate, ToolFormat

tg = TrustGate()   # TRUSTGATE_API_KEY
```

The key is the whole configuration, or nothing if it is in the environment.
The gateway it belongs to, and the applications behind it, are asked for:
`tg.identity()` asks once and remembers it. Set `TRUSTGATE_URL` (or `base_url`)
only for a Hybrid gateway, to the MCP host its own data plane is published on:
the NeuralTrust cloud does not serve that gateway.

```python
identity = tg.identity()
# identity.key -> KeyInfo(name="prod", expires_at=None)   # None means never
# KeyConsumer(slug="support-agent", type="MCP", url="https://…/support-agent/mcp",
#             upstreams=[KeyUpstream(server="Notion", account="shared", connected=True)])
# KeyConsumer(slug="support-llm",   type="LLM", url="https://…/support-llm/v1")
```

`key.expires_at` is the 401 you would otherwise meet mid-run, and `upstreams`
is the refusal you would otherwise meet on the first tool call — both answered
before anything starts.

`mcp_consumer` and `llm_consumer` (or `TRUSTGATE_MCP_CONSUMER` /
`TRUSTGATE_LLM_CONSUMER`) are only needed when a key reaches two applications on
the same plane — the SDK names them and refuses rather than guessing.

## An agent that acts as the application

```python
agent = tg.connect(requires=["search"])

agent.mcp                                        # url + headers for a framework
tg.llm()                                         # base_url for OpenAI, anthropic_base_url for Anthropic
toolkit = agent.toolkit(ToolFormat.OPENAI_RESPONSES)
agent.call_tool("search", {"query": "runbook"})
agent.refresh()                                  # re-read the toolkit
agent.connections                                # its own upstream accounts
```

A batch that must not stop halfway:

```python
try:
    agent = tg.connect(requires=["search"])
except UpstreamNotConnectedError as error:
    sys.exit(str(error))   # names each server and who fixes it

for row in rows:
    agent.call_tool("search", {"query": row.query})
```

With `requires`, only the servers behind those tools have to be connected: a
Linear nobody connected does not stop an agent that only calls Notion. Without
it, every server is one the agent may call, so any of them blocks the start.

The gateway serves a tool under the server it came from - Notion's `search` as
`notion_search` - so two servers with a `search` stay apart. That prefix is the
gateway's, so `requires` and `call_tool` take the name the server itself gave the
tool and add it; naming a tool two of your servers serve is the one case they
ask instead.

## An agent acting for one of its users

```python
alice = tg.for_end_user("user_123")
# or, from an agent you already have - no round trip, same toolkit:
bob = agent.for_end_user("user_456")

alice.connections()
alice.connect_link("com.notion/mcp")
alice.toolkit(ToolFormat.ANTHROPIC_MESSAGES)
```

A connection with `shared=True` holds one account for every caller: its status
is that account's, and no link of the user's fixes it, so an administrator
connects it in the console. `connect_link(instance=connection.instance)` names
one of two instances of the same server.

Both handles work on the same application and the same key: who a call runs as
comes from the call, not from anything configured on the application. The name is
yours to choose and the gateway namespaces it, so two applications naming
`user_123` never reach the same account.

## An agent for yourself, signed in

No application and no API key: sign in through the browser and get your own
Store - the servers you installed, narrowed to what Access grants you.

```python
me = TrustGate.login(url="https://acme.mcp.neuraltrust.ai/store/mcp").connect()

if me.needs_connect:  # servers whose account you have not connected yet
    print("Connect:", me.connect_link().connect_url)
toolkit = me.toolkit(ToolFormat.ANTHROPIC_MESSAGES)
```

The first run opens the browser; the session is kept in `~/.trustgate/sessions.json`
(owner-only) and renewed until the sign-in ends, a day on NeuralTrust's cloud.
Then `LoginRequiredError` says to sign in again. `cache=MemoryTokenCache()`
keeps nothing on disk, `force=True` signs in again regardless, and a backend
that already holds a token uses `TrustGateUser(url, access_token=...)`.

## The model call, with tools

```python
toolkit = agent.toolkit(ToolFormat.OPENAI_RESPONSES, strict=True)
for warning in toolkit.warnings:
    log.warning("%s could not be strict: %s", warning.tool, warning.reason)

response = client.responses.create(model="gpt-5.2", tools=toolkit.tools, input=messages)
while any(item.type == "function_call" for item in response.output):
    response = client.responses.create(
        model="gpt-5.2",
        tools=toolkit.tools,
        previous_response_id=response.id,
        input=toolkit.execute(response.output),
    )
```

`execute()` reads the provider's own objects as well as plain dicts, so the
response from the OpenAI or Anthropic SDK can be passed straight in.

## Your own HTTP client

```python
tg = TrustGate(..., transport=MyTransport())
```

`Transport` is a one-method protocol. The default is `UrllibTransport`; the
tests use a fake one. It is also where a retry policy or a proxy belongs.

## Errors

| Class | When |
|---|---|
| `MissingToolsError` | `requires` names a tool the application (or your Store) does not serve |
| `UpstreamNotConnectedError` | a server the call needs has no account behind it, at startup or on a call; `servers` names them and the message says who connects it - never a link |
| `ConsentRequiredError` | an end user has not connected; carries `connect_url` |
| `LoginRequiredError` | a signed-in session has ended and cannot be renewed; call `TrustGate.login()` again |
| `PolicyBlockedError` | a gateway policy refused the call |
| `ToolNotFoundError` | the tool left the toolkit under a running agent |
| `PlaneUnavailableError` | the key reaches no application on that plane |
| `AuthenticationError`, `RateLimitedError`, `ServiceUnavailableError`, `TrustGateServerError` | as named |

## Documentation

The full guide lives at [docs.neuraltrust.ai](https://docs.neuraltrust.ai/sdks/trustgate/overview):

| Page | What it covers |
|---|---|
| [Quickstart](https://docs.neuraltrust.ai/sdks/trustgate/overview) | Install, one key, `connect()`'s startup check, `identity()` |
| [Tools](https://docs.neuraltrust.ai/sdks/trustgate/tools) | The MCP endpoint for a framework, or toolkits for a provider's API |
| [Acting for end users](https://docs.neuraltrust.ai/sdks/trustgate/end-users) | Per-user accounts, consent errors, connect links |
| [Models](https://docs.neuraltrust.ai/sdks/trustgate/models) | A provider's own client pointed at the LLM plane |
| [Configuration](https://docs.neuraltrust.ai/sdks/trustgate/configuration) | Every option and environment variable, Hybrid gateways, regions |
| [Errors](https://docs.neuraltrust.ai/sdks/trustgate/errors) | Every failure, and whose it is to fix |

The same SDK for TypeScript: [`@neuraltrust/trustgate` on npm](https://www.npmjs.com/package/@neuraltrust/trustgate). Source,
examples and issues: [github.com/NeuralTrust/trustgate-sdk](https://github.com/NeuralTrust/trustgate-sdk).

## Development

```bash
uv sync --extra dev
uv run pytest
```

[CONTRIBUTING.md](https://github.com/NeuralTrust/trustgate-sdk/blob/main/CONTRIBUTING.md) has every check CI runs.
