Skip to main content
When you write the agent yourself, the URL is the easy part. MCP does not carry who a call runs as, which credential it travels with, or what to do when an upstream account is not connected. The TrustGate SDK exists to answer those three, in Python and TypeScript, with the same behaviour in both. An agent that already speaks MCP, such as Claude Code or Cursor, does not need the SDK. It needs a URL and a way to sign in: see Connect an agent.

Install

Both packages have no runtime dependencies: the Python one uses the standard library, the TypeScript one the global fetch.
Install trustgate-sdk, not trustgate: the trustgate package on PyPI is a different, unrelated project that uses the same import name. Check with pip show trustgate-sdk.
The packages are trustgate-sdk on PyPI and @neuraltrust/trustgate on npm. Each one’s README carries a short version of this guide in its language, and the repository holds the source, runnable examples and the issue tracker.

One key, nothing else

The key is the application’s own, issued from its Auth tab in the console. A person’s own personal key is refused here: it runs as its owner, not as an application, and opens their own Store through TrustGateUser. The gateway it belongs to and the addresses the application is served on never travel with it, so the SDK asks: it sends the key to https://agentgateway-mcp.neuraltrust.ai, which finds the gateway from the key and answers with that gateway’s own addresses. Keys from another region are not found there. Set TRUSTGATE_URL to that region’s discovery host. The published hosts are listed under Regions and environments. From then on the SDK talks only to those. You name nothing else unless one key reaches two applications on the same plane, which the SDK refuses to guess at. A Hybrid gateway also needs an address. See Configuration.

Check the run before it starts

connect() is the application acting as itself, with the key and nothing else. It proves two things before returning:
  1. The servers behind it have an account. A batch has nobody to open a connect link once it is running, so the check comes before the first row. The message names who has to act: an administrator, for a server whose one account every caller shares, or your code, with the line to write, for a server that keeps an account per user.
  2. The tools you need are there. The tool set belongs to an admin and can be narrowed without warning. requires turns that into a refusal at startup instead of a failure mid-conversation.
Name tools as their own server names them: search, not the <server>_<tool> name the gateway publishes. The gateway does not resolve a short name: tools/call needs the listed name or, for now, a spelling from before the current naming (see Tool names). Any other name is an unknown tool (JSON-RPC -32602), or is refused as not permitted when the application’s toolkit denies it. The SDK matches the name you pass against the application’s tool list. One listed tool that ends in _<name> is used. When more than one does, it asks which you mean. When none does, it sends the name unchanged. Names that gained a collision suffix or were shortened to fit 64 characters can’t be matched this way; call them by the name in agent.tools. In TypeScript, a handle from forEndUser() does not match short names: pass callTool() the full name from tools.

What the key reaches

identity() answers what connect() reads, without connecting: the gateway, when the key expires, and for each application its plane, its address and which servers are still waiting for an account. It is asked once and remembered.
The whoami example in the SDK repository prints all of it. Run it first when something is off.

Next