openai-workspace-mcp
This server exposes the OpenAI Admin API (organization back office) as MCP tools, letting you manage organization members, invites, projects, project members, service accounts, project API keys, rate limits, and query usage, costs, and audit logs.
Organization Users — list members (with optional email filter), get user details, change a member's org role (owner/reader), and remove members.
Invites — invite new users by email (with org role and optional project memberships), get invite status, list invites, and revoke pending invites.
Projects — list (optionally including archived), get details, create, rename, and archive projects (archiving is irreversible via API).
Project Users — list project members, get membership details, add existing org members to a project, change project roles, and remove members.
Service Accounts — list, get, create (response returns the plaintext API key once), update name/role, and delete service accounts. Creating one is the only way to mint a new API key.
Project API Keys — list keys (values redacted) with owner-project-access filtering, get key details, and delete keys (except service-account-owned keys).
Project Rate Limits — list per-model rate limit configs and update limits (requests/min, tokens/min, images/min, audio MB/min, requests/day, batch input tokens/day).
Usage & Costs — query time-bucketed usage by category (completions, embeddings, moderations, images, audio, vector stores, code interpreter, file search, web search) with grouping/filtering, and query daily spend breakdown (up to 180 buckets).
Audit Logs — list user actions and config changes filtered by time, actors, event types, projects, and resources.
Provides tools for interacting with the OpenAI Admin API, enabling management of organization members, invites, projects, project members, service accounts, project API keys, rate limits, usage, costs, and audit logs.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@openai-workspace-mcp what's my API usage this month?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
openai-workspace-mcp
OpenAI Workspace MCP server for Claude — exposes the OpenAI Admin API (the API Platform organization back office, distinct from ChatGPT Enterprise workspace admin) as MCP tools: organization members, invites, projects, project members, service accounts, project API keys, rate limits, usage, costs, and audit logs.
Tech stack: Python 3.12 + uv + FastMCP (Starlette/uvicorn)
Related requirement: PRD-15751 (ChatGPT / OpenAI Workspace). See the full research in
vendor-mcp-template/prd/OpenAIWorkspace.md.
Out of scope: Admin API key self-management, fine-grained custom Roles/Groups (RBAC), mTLS Certificates, Data Retention policy, Spend Limit/Alert configuration, Model Permissions, and Hosted Tool Permissions are intentionally not implemented — see the PRD §4.11 for rationale (mostly: high-risk security/compliance writes, or orthogonal to the "members + usage + billing" scope this service targets).
MSPbots Connector
The MCP Gateway built for MSPs: visible, controlled, and your data stays where it belongs.
Get started at connect.mspbots.ai →
MSPbots Connector gives your AI clients one MCP URL to reach your entire MSP stack (RMM, PSA, documentation, security, finance), and gives you control over who can call which tool and a record of everything that was called.
Hosted service: connect.mspbots.ai · Free to use.
Why Connector

Visible | Every tool call is logged: who, which vendor, when. Usage dashboard, CSV export, SIEM streaming. |
Controlled | Role-based, per-tool allowlist. Deny by default. |
Protected | Credentials encrypted per record. AI clients never see your vendor passwords or tokens. |
MSP-native | Built for the MSP stack only: RMM, PSA, documentation, security, finance. |
Quick start
Sign up at connect.mspbots.ai.
Connect your vendors. Pick from 150+ connectors and authorize each one on the vendor's own page, or bring your own API keys. No extra vendor accounts needed.
Set access. Create roles and decide which tools each role may call. Nothing is allowed until you allow it.
Add your MCP URL to your AI client. Copy the URL from your Connector dashboard into Claude, ChatGPT, Cursor, VS Code, Gemini, Codex, or any MCP-capable client.
Ask your AI to do real work, and watch every call appear in the audit log.
Features
Unified gateway
One MCP URL for all your AI clients
150+ connectors across the MSP stack
Custom MCP servers supported, free
Authorization happens on each vendor's own page; the AI never sees passwords or tokens
Bring your own credentials: use the vendor API keys you already have
Multiple accounts per app; connect once, reuse across AI clients
Tool search: finds the right action for the task
One sign-in; vendor credentials are injected behind the scenes and OAuth tokens refresh automatically
Visibility
Audit log for every tool call (who, which vendor, when)
Usage dashboard: call volume, top vendors, error rate, per-user activity
Export audit logs to CSV, or stream to Loki, Graylog, or LogScale (SIEM)
Optional recording of tool arguments and result summaries (off by default, enabled per organization)
Control
Per-role, per-tool allowlist, deny by default
owner / admin / member roles
SCIM provisioning with Entra ID, Okta, JumpCloud, and Google Workspace
Security
Credentials encrypted one record at a time (AES-256-GCM, per-record key)
AI clients authenticate with OAuth 2.1 + PKCE
Vendor responses are scanned for prompt-injection patterns and returned as structured data. This is one layer of defense, not a guarantee against every attack.
Static egress IP for customer firewall and API allowlisting
Pricing
Free.
Links: connect.mspbots.ai · mspbots.ai
Related MCP server: OpenAI Assistant MCP Server
Quick Start
cd openai-workspace-mcp
uv sync
# stdio mode (for Claude Desktop / CLI), single shared key from env
OPENAI_ADMIN_API_KEY=sk-admin-xxxx uv run openai-workspace-mcpAuthentication
This service is stateless: it never stores or persists the OpenAI Admin API key.
The key is either supplied once via an environment variable (local dev, AUTH_MODE=env),
or per-request via an HTTP header (AUTH_MODE=gateway, production).
Unlike some other vendor integrations in this workspace (Adobe, Bitwarden), the OpenAI Admin API needs no OAuth token exchange — it's a single static Bearer token attached directly to every request, so there's no extra Identity round trip.
Gateway mode HTTP headers (AUTH_MODE=gateway)
Header | Type | Required | Default | Enum | Description | Example |
| string | Yes | none | none | OpenAI Admin API key ( |
|
Missing the header on a /mcp request returns 401 with a required_headers list.
Env mode variables (AUTH_MODE=env, local dev only)
Variable | Default | Description |
| — | OpenAI Admin API key |
|
| Admin API base URL (fixed, no regional variants) |
|
|
|
|
|
|
|
| HTTP server port |
|
| HTTP server bind address |
Get a key: as an organization Owner, go to platform.openai.com -> Settings -> Admin API Keys -> Create. Requires an OpenAI API Platform organization (not a personal ChatGPT account).
Claude Desktop Setup
{
"mcpServers": {
"openai-workspace": {
"command": "uv",
"args": ["run", "--directory", "/path/to/openai-workspace-mcp", "openai-workspace-mcp"],
"env": {
"OPENAI_ADMIN_API_KEY": "sk-admin-xxxx"
}
}
}
}Transport Modes
stdio (Claude Desktop / CLI)
OPENAI_ADMIN_API_KEY=sk-admin-xxxx uv run openai-workspace-mcpHTTP — single-tenant (env mode)
OPENAI_ADMIN_API_KEY=sk-admin-xxxx MCP_TRANSPORT=http AUTH_MODE=env uv run openai-workspace-mcp
curl http://localhost:8080/healthHTTP — gateway / multi-tenant (production)
MCP_TRANSPORT=http AUTH_MODE=gateway uv run openai-workspace-mcpTool List
Base URL: https://api.openai.com/v1 (fixed). List endpoints use cursor pagination
(after/limit, some also before) — pass the previous response's last_id/next_page
value as after/page to fetch the next batch.
Organization Users
Tool | Description | Parameters |
| List organization members |
|
| Get a member's details |
|
| Change a member's org role |
|
| Remove a member from the org |
|
No "create user" endpoint — joining the org always goes through an invite.
Invites
Tool | Description | Parameters |
| Invite a new user by email |
|
| Get an invite's status |
|
| List all invites |
|
| Revoke a pending invite |
|
Projects
Tool | Description | Parameters |
| List projects |
|
| Get a project's details |
|
| Create a project |
|
| Rename a project |
|
| Archive a project (cannot be undone via API; projects cannot be deleted) |
|
Project Users
Tool | Description | Parameters |
| List members of a project |
|
| Get a project member's details |
|
| Add an existing org member to a project |
|
| Change a member's project role |
|
| Remove a member from a project |
|
Project Service Accounts
Service accounts are non-human, project-scoped identities. Creating one is the only programmatic way to mint a new API key — there's no "create user API key" endpoint.
Tool | Description | Parameters |
| List service accounts in a project |
|
| Get a service account's details |
|
| Create a service account (response includes the API key's plaintext value — shown only once) |
|
| Update name/role |
|
| Delete a service account |
|
Project API Keys (read + revoke only)
Tool | Description | Parameters |
| List API keys in a project (values always redacted) |
|
| Get a key's details (redacted) |
|
| Delete a key (fails if it belongs to a service account — delete the service account instead) |
|
Project Rate Limits
Tool | Description | Parameters |
| List per-model rate limit configs |
|
| Update one model's rate limit |
|
Usage & Costs
Tool | Description | Parameters |
| Query time-bucketed usage for one category |
|
| Query daily spend breakdown |
|
Audit Logs
Tool | Description | Parameters |
| List user actions and config changes |
|
Role enums: org — owner/reader; project & service account — owner/member (service
account also has read-only none). Invite status (read-only): pending/accepted/expired.
Rate limits: OpenAI has not published Admin-API-specific throttling numbers; 429
responses are passed through as-is.
Test Examples
tools/list (gateway mode)
curl -X POST http://localhost:8080/mcp \
-H "x-openai-admin-key: sk-admin-your_key" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'tools/call — invite a member into a project
curl -X POST http://localhost:8080/mcp \
-H "x-openai-admin-key: sk-admin-your_key" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 2,
"params": {
"name": "openai_invite_user",
"arguments": {
"email": "user@example.com",
"role": "reader",
"projects": [{"id": "proj_abc123", "role": "member"}]
}
}
}'tools/call — query last 7 days of completions usage
curl -X POST http://localhost:8080/mcp \
-H "x-openai-admin-key: sk-admin-your_key" \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"id": 3,
"params": {
"name": "openai_get_usage",
"arguments": {"category": "completions", "start_time": 1735689600, "bucket_width": "1d", "limit": 7}
}
}'Missing header → 401
curl -i -X POST http://localhost:8080/mcp \
-H "Content-Type: application/json" \
-H "Accept: application/json, text/event-stream" \
-d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
# HTTP/1.1 401 Unauthorized
# {"error":"Missing credentials","required_headers":["x-openai-admin-key"]}API Reference
Endpoint paths, params, and enums in this service were verified against the official
openai-nodeSDK source (src/resources/admin/organization/**, auto-generated by OpenAI from their OpenAPI spec), since the interactive docs site returns 403 to non-browser fetches. Seevendor-mcp-template/prd/OpenAIWorkspace.md§8 for the exact file list.
Known Limitations
No "create user" or "create project API key" tools — by design, these follow OpenAI's own API surface: org membership only grows via invites, and a new API key can only be minted by creating a service account.
openai_create_service_accountreturns a plaintext API key — this is the underlying API's own behavior (shown once, at creation time only); the tool does not redact it.Array-valued filters (
project_ids,event_types, etc.) are sent askey[]=...query params, matching OpenAI's own SDK serialization — not the plain repeated-key format some other vendors in this workspace use.No documented Admin-API-specific rate limits —
429is passed through as-is.Requires an OpenAI API Platform organization with Owner access to create an Admin API key; a personal ChatGPT account cannot use this service.
Advanced features intentionally out of scope: Admin API key self-management, custom Roles/Groups (RBAC), Certificates (mTLS), Data Retention, Spend Limit/Alerts, Model Permissions, Hosted Tool Permissions — see the PRD for rationale.
Available Tools
31 toolsopenai_add_project_userA
Add an existing organization member to a project.
The user must already be a member of the organization (see
openai_invite_user / openai_list_users) — this call cannot invite
someone new to the org.
Args:
project_id: The project's ID (see openai_list_projects).
user_id: The organization member's user ID (see openai_list_users).
role: Project role to grant — `owner` or `member`.
Inputs: role (required), user_id (required), project_id (required). Returns: result
openai_archive_projectA
Archive a project. Archived projects cannot be used or modified further, and this action cannot be undone via the API.
Args:
project_id: The project's ID (see openai_list_projects).
Inputs: project_id (required). Returns: result
openai_create_projectA
Create a new project in the organization.
Args:
name: The project's friendly name (appears in usage/cost reports).
Inputs: name (required). Returns: result
openai_create_service_accountA
Create a new service account in a project.
By default this also creates a `member`-role project membership and an
API key for the account. IMPORTANT: the response contains the API key's
PLAINTEXT value — this is the only time it is ever shown. Surface it to
the user immediately so they can store it; it cannot be retrieved again.
Args:
project_id: The project's ID (see openai_list_projects).
name: Name for the new service account.
create_service_account_only: If True, skip creating the default role/API key.
Inputs: name (required), project_id (required), create_service_account_only. Returns: result
openai_delete_inviteA
Revoke a pending invite. Invites that have already been accepted cannot be deleted.
Args:
invite_id: The invite's ID (see openai_list_invites).
Inputs: invite_id (required). Returns: result
openai_delete_project_api_keyA
Delete an API key from a project.
Fails if the key belongs to a service account — delete the service
account instead (openai_delete_service_account) to revoke that key.
Args:
project_id: The project's ID (see openai_list_projects).
api_key_id: The API key's ID (see openai_list_project_api_keys).
Inputs: api_key_id (required), project_id (required). Returns: result
openai_delete_service_accountA
Delete a service account from a project. Fails if the project is archived.
Args:
project_id: The project's ID (see openai_list_projects).
service_account_id: The service account's ID (see openai_list_service_accounts).
Inputs: project_id (required), service_account_id (required). Returns: result
openai_get_costsA
Query the organization's daily spend breakdown.
Args:
start_time: Start of the query range, inclusive (Unix seconds).
end_time: End of the query range, exclusive (Unix seconds).
bucket_width: Time bucket size — only `1d` is currently supported.
group_by: Fields to group by — project_id, line_item, api_key_id.
project_ids: Only include costs for these projects.
api_key_ids: Only include costs for these API keys.
limit: Number of buckets to return (1-180, default 7).
page: Pagination cursor from a previous response's `next_page`.
Inputs: start_time (required), page, limit, end_time, +4 more. Returns: result
openai_get_inviteA
Get a single invite's details, including its status.
Args:
invite_id: The invite's ID (see openai_list_invites).
Inputs: invite_id (required). Returns: result
openai_get_projectA
Get a single project's details.
Args:
project_id: The project's ID (see openai_list_projects).
Inputs: project_id (required). Returns: result
openai_get_project_api_keyA
Get a single project API key's details (redacted value only).
Args:
project_id: The project's ID (see openai_list_projects).
api_key_id: The API key's ID (see openai_list_project_api_keys).
Inputs: api_key_id (required), project_id (required). Returns: result
openai_get_project_userA
Get a single project member's details.
Args:
project_id: The project's ID (see openai_list_projects).
user_id: The member's user ID (see openai_list_project_users).
Inputs: user_id (required), project_id (required). Returns: result
openai_get_service_accountA
Get a single service account's details.
Args:
project_id: The project's ID (see openai_list_projects).
service_account_id: The service account's ID (see openai_list_service_accounts).
Inputs: project_id (required), service_account_id (required). Returns: result
openai_get_usageA
Query time-bucketed API usage for the organization.
`limit` caps the number of time buckets returned, with different
defaults/maximums per bucket_width: 1d -> default 7, max 31; 1h ->
default 24, max 168; 1m -> default 60, max 1440.
Args:
category: Which usage type to query — one of: completions,
embeddings, moderations, images, audio_speeches,
audio_transcriptions, vector_stores, code_interpreter_sessions,
file_search_calls, web_search_calls.
start_time: Start of the query range, inclusive (Unix seconds).
end_time: End of the query range, exclusive (Unix seconds).
bucket_width: Time bucket size — `1m`, `1h`, or `1d` (default `1d`).
group_by: Fields to group by, e.g. project_id, user_id, api_key_id,
model, batch, service_tier (supported fields vary by category).
project_ids: Only include usage for these projects.
user_ids: Only include usage for these users.
api_key_ids: Only include usage for these API keys.
models: Only include usage for these models.
limit: Number of time buckets to return.
page: Pagination cursor from a previous response's `next_page`.
Inputs: category (required), start_time (required), page, limit, +7 more. Returns: result
openai_get_userA
Get a single organization member's details.
Args:
user_id: The member's user ID (see openai_list_users).
Inputs: user_id (required). Returns: result
openai_invite_userA
Invite a new user to the OpenAI organization by email.
The invite must be accepted by the user before they gain access. Its
"status" starts at `pending` until accepted.
Args:
email: Email address to invite.
role: Organization role to grant — `owner` or `reader`.
projects: Optional list of `{"id": <project_id>, "role": "owner"|"member"}`
to grant project membership at the same time the invite is accepted.
If omitted, the user is invited to the default project (legacy
behavior). Pass an empty list to invite them to no projects at all.
Inputs: role (required), email (required), projects. Returns: result
openai_list_audit_logsA
List user actions and configuration changes in the organization.
Args:
effective_start_time: Only events at/after this Unix timestamp (seconds).
effective_end_time: Only events before this Unix timestamp (seconds).
actor_emails: Only events performed by users with these emails.
actor_ids: Only events performed by these actors (user, service
account, or API key tracking IDs).
event_types: Only events of these types, e.g. `project.created`,
`user.added`, `api_key.deleted`, `invite.sent`. See
https://platform.openai.com/docs/api-reference/audit-logs/object
for the full enum.
project_ids: Only events scoped to these projects.
resource_ids: Only events affecting these resource IDs.
after: Pagination cursor from a previous response's `last_id`.
before: Pagination cursor to fetch the previous page.
limit: Maximum number of events to return per page.
Inputs: after, limit, before, actor_ids, +6 more. Returns: result
openai_list_invitesA
List all invites in the organization.
Each invite's "status" is one of `pending`, `accepted`, or `expired`.
Args:
after: Pagination cursor from a previous response's `last_id`.
limit: Maximum number of invites to return per page.
Inputs: after, limit. Returns: result
openai_list_project_api_keysA
List API keys in a project. Key values are always redacted.
Args:
project_id: The project's ID (see openai_list_projects).
owner_project_access: Filter by whether the key owner currently has
project access — `active`, `inactive`, or `any`.
after: Pagination cursor from a previous response's `last_id`.
limit: Maximum number of keys to return per page.
Inputs: project_id (required), after, limit, owner_project_access. Returns: result
openai_list_projectsA
List projects in the organization.
Args:
include_archived: If True, also return archived projects (excluded by default).
after: Pagination cursor from a previous response's `last_id`.
limit: Maximum number of projects to return per page.
Inputs: after, limit, include_archived. Returns: result
openai_list_project_usersA
List members of a project.
Args:
project_id: The project's ID (see openai_list_projects).
after: Pagination cursor from a previous response's `last_id`.
limit: Maximum number of users to return per page.
Inputs: project_id (required), after, limit. Returns: result
openai_list_rate_limitsA
List per-model rate limit configs for a project.
Args:
project_id: The project's ID (see openai_list_projects).
after: Pagination cursor from a previous response's `last_id`.
before: Pagination cursor to fetch the previous page.
limit: Maximum number of rate limit entries to return per page.
Inputs: project_id (required), after, limit, before. Returns: result
openai_list_service_accountsA
List service accounts in a project.
Args:
project_id: The project's ID (see openai_list_projects).
after: Pagination cursor from a previous response's `last_id`.
limit: Maximum number of service accounts to return per page.
Inputs: project_id (required), after, limit. Returns: result
openai_list_usersA
List members of the OpenAI organization.
Args:
emails: Filter by these email addresses.
after: Pagination cursor from a previous response's `last_id`.
limit: Maximum number of users to return per page.
Inputs: after, limit, emails. Returns: result
openai_remove_project_userA
Remove a member from a project. Fails if the project is archived.
Args:
project_id: The project's ID (see openai_list_projects).
user_id: The member's user ID (see openai_list_project_users).
Inputs: user_id (required), project_id (required). Returns: result
openai_remove_userA
Remove a member from the organization.
Args:
user_id: The member's user ID (see openai_list_users).
Inputs: user_id (required). Returns: result
openai_update_projectA
Rename a project.
Args:
project_id: The project's ID (see openai_list_projects).
name: The new project name.
Inputs: name (required), project_id (required). Returns: result
openai_update_project_user_roleA
Change a member's role within a project.
Args:
project_id: The project's ID (see openai_list_projects).
user_id: The member's user ID (see openai_list_project_users).
role: New project role — `owner` or `member`.
Inputs: role (required), user_id (required), project_id (required). Returns: result
openai_update_rate_limitA
Update a project's rate limit for one model.
Each `max_*` field only applies to relevant model types (e.g.
max_images_per_1_minute only matters for image models) — check
openai_list_rate_limits first to see which fields are present for the
target model before changing them.
Args:
project_id: The project's ID (see openai_list_projects).
rate_limit_id: The rate limit entry's ID (see openai_list_rate_limits).
max_requests_per_1_minute: New requests-per-minute limit.
max_tokens_per_1_minute: New tokens-per-minute limit.
max_images_per_1_minute: New images-per-minute limit.
max_audio_megabytes_per_1_minute: New audio-megabytes-per-minute limit.
max_requests_per_1_day: New requests-per-day limit.
batch_1_day_max_input_tokens: New batch max input tokens per day.
Inputs: project_id (required), rate_limit_id (required), max_requests_per_1_day, max_images_per_1_minute, +4 more. Returns: result
openai_update_service_accountA
Update a service account's name and/or role.
Args:
project_id: The project's ID (see openai_list_projects).
service_account_id: The service account's ID (see openai_list_service_accounts).
name: New name for the service account.
role: New project role — `owner` or `member`.
Inputs: project_id (required), service_account_id (required), name, role. Returns: result
openai_update_user_roleA
Change a member's role in the organization.
Args:
user_id: The member's user ID (see openai_list_users).
role: New organization role — `owner` or `reader`.
Inputs: role (required), user_id (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 31 tools
Each tool targets a distinct resource/action pair, and the descriptions are clear. A few similarly named tools (e.g., update_project_user_role vs update_user_role, add_project_user vs invite_user) could cause misselection, but their scopes are still distinguishable.
The openai_ prefix and a general verb_noun pattern are consistently used. Minor deviations like mixing 'remove' and 'delete' for destructive actions, and 'invite_user' instead of 'create_invite', prevent a perfect score.
At 31 tools, the set exceeds the 'too many' threshold of 25. While the broad domain explains the number, the granularity feels heavy and could have been consolidated (e.g., fewer separate get/list operations).
The surface nearly covers all management workflows for projects, users, invites, service accounts, API keys, rate limits, audit logs, usage, and costs. Notable gaps are a standalone API key creation tool and unarchiving projects, but these are edge cases rather than major holes.
Maintenance
Related MCP Connectors
Your org's AI agents, tasks, runs, search, and brain files as MCP tools and resources.
OpenAI organization usage and cost reporting through an admin API key connected by the user.
Authenticated MCP Agent (Openai)
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
Related MCP Servers
- AlicenseBqualityDmaintenanceProvides tools to manage OpenAI API keys and spending through the OpenAI API. Requires an OpenAI admin API key for secure access to account management features.2MIT
- FlicenseBqualityDmaintenanceEnables interaction with OpenAI's Chat Completion and Assistants APIs, supporting assistant management, file operations, and direct queries to GPT models through standardized MCP tools.92-
- AlicenseAqualityDmaintenanceFull coverage of Anthropic Admin API to manage organization, workspaces, members, API keys, usage, and costs via natural language from any MCP client.21109 PyPIMIT
- FlicenseNot gradedqualityDmaintenanceExposes LiteLLM Proxy admin APIs as MCP tools for managing internal users, virtual keys, and spend logs via streamable-http, enabling agents to administer LiteLLM without custom HTTP glue.1-