> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xentfi.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Remote HTTP Deployment

> Run xentfi-mcp-http, a stateless multi-tenant Streamable HTTP MCP server, for ChatGPT connectors and shared deployments.

Use this when you need a **hosted, network-reachable** MCP endpoint instead of a locally-spawned stdio process — e.g. for ChatGPT custom connectors, a shared team deployment fronting several MCP clients, or any MCP client that only supports remote servers.

## How it works

`xentfi-mcp-http` starts an Express server implementing the MCP **Streamable HTTP** transport on `POST /mcp` (plus a `GET /healthz` health check). It runs in **stateless mode**: every request creates a fresh MCP server + client pair bound to *that request's* credentials, then tears it down.

```mermaid theme={null}
sequenceDiagram
    participant Agent as MCP Client (ChatGPT, etc.)
    participant HTTP as xentfi-mcp-http
    participant API as XentFi API

    Agent->>HTTP: POST /mcp<br/>Authorization: Bearer sk_agent_xxx
    HTTP->>HTTP: Build fresh McpServer + XentfiClient<br/>bound to this request's key
    HTTP->>API: tools/call → /v1/agent-self/...
    API-->>HTTP: response
    HTTP-->>Agent: MCP tool result
    HTTP->>HTTP: Tear down server + transport
```

This means:

* One process can safely serve **many different agents/organizations** at once — credentials never leak between requests.
* There is no server-side session state to persist or scale; you can run multiple replicas behind a load balancer with no sticky-session requirement.
* Each request is a little more expensive than a long-lived stdio connection (fresh server per call) — the right trade-off for a multi-tenant deployment, and negligible in practice.

## Running it

```bash theme={null}
npm install @xentfi/mcp-server
npx xentfi-mcp-http
# [xentfi-mcp-http] Listening on http://localhost:8787/mcp (health check: /healthz)
```

| Variable                           | Default                     | Purpose                                                                                                                                |
| ---------------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| `PORT` / `XENTFI_MCP_PORT`         | `8787`                      | Port to listen on.                                                                                                                     |
| `XENTFI_MCP_PATH`                  | `/mcp`                      | Path for the MCP endpoint.                                                                                                             |
| `XENTFI_BASE_URL`                  | `https://api.xentfi.com/v1` | XentFi API base URL.                                                                                                                   |
| `XENTFI_API_KEY` / `XENTFI_ORG_ID` | *(unset)*                   | **Fallback only** — used when an incoming request doesn't supply its own auth headers. Leave unset for a true multi-tenant deployment. |

## Authenticating requests

Every `POST /mcp` call must carry the caller's agent credentials as headers:

```
Authorization: Bearer <agent-api-key>
x-xentfi-org-id: <org-id>          # optional, only for market-data tools
```

`x-xentfi-api-key` is also accepted as an alternative to `Authorization`, for clients that can't set that header freely. Requests without a resolvable API key receive a `401` JSON-RPC error before any XentFi API call is attempted.

## Deployment recipes

<CodeGroup>
  ```dockerfile Dockerfile theme={null}
  FROM node:20-slim
  WORKDIR /app
  RUN npm install @xentfi/mcp-server
  EXPOSE 8787
  ENV XENTFI_MCP_PORT=8787
  CMD ["npx", "xentfi-mcp-http"]
  ```

  ```bash Build & run theme={null}
  docker build -t xentfi-mcp-http .
  docker run -p 8787:8787 xentfi-mcp-http
  ```

  ```caddyfile Caddy reverse proxy (TLS) theme={null}
  xentfi-mcp.yourcompany.com {
      reverse_proxy localhost:8787
  }
  ```
</CodeGroup>

<Note>
  Put this behind a TLS-terminating reverse proxy — MCP clients like ChatGPT require HTTPS. Fly.io, Render, and Railway all provision HTTPS automatically if you point them at the Dockerfile above.
</Note>

## Testing your deployment

```bash theme={null}
curl https://xentfi-mcp.yourcompany.com/healthz
# {"status":"ok","service":"xentfi-mcp-http"}

curl -X POST https://xentfi-mcp.yourcompany.com/mcp \
  -H "Authorization: Bearer sk_agent_xxx" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

You should get back the JSON-RPC response listing all 15 `xentfi_*` tools.

## Programmatic embedding

If you're already running your own Express (or other Node HTTP) server and want to mount XentFi's MCP tools at a custom path alongside other routes, use `createXentfiMcpServer()` directly instead of the `xentfi-mcp-http` binary:

```ts theme={null}
import { createXentfiMcpServer } from "@xentfi/mcp-server";
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";

app.post("/mcp", async (req, res) => {
  const apiKey = req.header("authorization")?.replace(/^Bearer\s+/i, "");
  const orgId = req.header("x-xentfi-org-id");
  if (!apiKey) return res.status(401).json({ error: "missing api key" });

  const server = createXentfiMcpServer({ apiKey, orgId });
  const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
  res.on("close", () => { transport.close(); server.close(); });

  await server.connect(transport);
  await transport.handleRequest(req, res, req.body);
});
```

## Next steps

<CardGroup cols={2}>
  <Card title="ChatGPT" icon="bot" href="/agent/chatgpt">
    Wire this deployment into a ChatGPT custom connector.
  </Card>

  <Card title="Error Handling" icon="alert-triangle" href="/agent/errors">
    How auth and policy failures surface over HTTP.
  </Card>
</CardGroup>
