Iblai api agent mcp
MCP connectors for ibl.ai agents, end to end — register MCP servers (featured multi-tenant sharing, enable/disable, OAuth service linkage), manage credential connections with the auth_type × scope matrix (org / agent / per-user), wire servers onto an agent, run the OAuth connected-service lifecycle, handle per-user in-chat OAuth (the oauth_required / oauth_connection_resolved chat events), and debug MCP auth failures (401s, missing OAuth prompts, agents ignoring servers). Use when wiring an agent to external MCP servers and tools, or designing/troubleshooting MCP auth.From its SKILL.md
npx -y skills add iblai/api --skill iblai-api-agent-mcpAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
4 things to look at
- reads credentialsReads from 3 credential sources: `IBLAI_API_KEY` and 2 more.
- 15 stars15 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 1 command, including `/iblai-api-login`.
- fetches URLsInstructs the agent to fetch 5 URLs, including https://api.iblai.app/dm/api/ai-mentor/orgs/{org}/users/{username}/mcp-servers/ and 4 more.
SKILL.md
19.7 KB, ~5.0k tokens by cl100k_base, as published. Nobody here has run it
iblai-api-agent-mcp
Configure external MCP tool access for agents. The platform models MCP with three objects, and a working integration always requires all three:
- MCP server — metadata for the external MCP endpoint (name, URL,
transport,
auth_type,auth_scope). - MCP server connection — the credential binding (a static token, or a
reference to an OAuth connected service), at
platform,mentor(agent), oruserscope. - Agent wiring — the agent's settings must have the
mcp-toolslug intool_slugsAND the server id inmcp_servers.
A missing step 3 is the most common failure mode: server and connection exist but the agent never calls them. Always finish by re-reading the agent's settings.
Auth & conventions
- Base URL:
https://api.iblai.app/dm— the/dmprefix is required. MCP endpoints live under/api/ai-mentor/orgs/{org}/users/{username}/...and OAuth connector endpoints under/api/ai-account/..., appended to it. (…in the endpoint lists below abbreviateshttps://api.iblai.app/dm/api/ai-mentor/orgs/{org}.) - The backend also accepts an
agent-spelled twin of every mentor route (/api/ai-agent/...,agents/formentors/); thementorspelling is canonical and used here, matching the other skills. - Header:
Authorization: Api-Token $IBLAI_API_KEYon every request. - Path vars:
{org}=$IBLAI_ORG,{username}=$IBLAI_USERNAME,{mentor}= the agent's unique id (UUID, e.g.d17dc729-60fd-4363-81a0-f67d9318b03e). - On the wire the agent noun is
mentor: body fields (mentor,mentor_unique_id) and the scope enum valuementorrefer to an agent. - DELETE / destructive calls: confirm with the user first. Never echo credentials or tokens back into chat, and never commit them to files.
- Not connected yet? Run
/iblai-api-loginfirst to populateIBLAI_ORG,IBLAI_USERNAME, andIBLAI_API_KEY.
Choosing the auth pattern
The auth_type × auth_scope decision on the server drives everything
downstream. auth_type = how credentials go on the wire (none | token | oauth2). auth_scope = whose credentials are used (platform | mentor | user). They are orthogonal.
| Pattern | Server fields | Connection setup | End user prompted? |
|---|---|---|---|
| No auth | auth_type=none | connection with no credentials | No |
| Shared key for the whole org | auth_type=token, auth_scope=platform | one platform-scoped connection holding the key | No |
| Per-agent key | auth_type=token, auth_scope=mentor | one mentor-scoped connection per agent | No |
| Pre-provisioned per-user | auth_scope=user | admin creates user-scoped connections up front | No |
| In-chat OAuth (each user connects their own account) | auth_type=oauth2 and auth_scope=user | none up front — created automatically when the user completes OAuth mid-chat | Yes |
Facts to keep straight:
auth_type="oauth2"+auth_scope="user"is the only combination that triggers the in-chat OAuth prompt;oauth2alone is not enough.- Any
oauth2connection (at any scope) requires aconnected_serviceid — an existing OAuth grant (see the connected-service lifecycle below). - In-chat OAuth servers must also link an
oauth_service(an OAuth service record id) on the server.
Runtime credential resolution
When an agent invokes an MCP server, credentials resolve in this order — first match wins:
- User-scoped connection for (server, user)
- Mentor-scoped connection for (server, agent)
- Platform-scoped connection for (server, org)
- Featured-server global fallback
- No connection → the call fails 401 — or the in-chat OAuth prompt
fires if the server is
auth_scope="user"+auth_type="oauth2"
OAuth-backed connections auto-refresh access tokens near expiry server-side; no client action is needed.
OAuth connected services (lifecycle)
Terminology: an OAuth provider is the vendor (google, dropbox); an
OAuth service is one surface of it (drive, calendar); a connected
service is a user's persisted token grant for one service — unique on
(user, provider, org, service).
Prerequisite: the org must have a credential named auth_{provider}
(containing client_id, client_secret, redirect_uri) in the credential
store before any flow can start — 400 "No credentials found" on the start
call means it is missing (install it via the integration-credential
endpoints, see /iblai-api-integration).
Flow: discover enabled services → start (returns an auth_url; open
it in a new tab — providers block iframes; the flow's state entry expires
after 1 hour) → the vendor redirects the user's browser to the
callback, which exchanges the code and returns the connected service →
use its id as connected_service on an MCP connection. If a grant already
existed for the same (user, provider, org, service), it is updated in place.
Reads
- GET
…/users/{username}/mcp-servers/?include_global=true&mentor_unique_id={mentor}&is_featured={true|false}&search={q}&transport={…}&page={n}&page_size=12— list MCP servers (paged;include_global=truesurfaces org-wide connectors;searchandtransportnarrow results). - GET
…/users/{username}/mcp-server-connections/— list connections: scope,is_active,server_name,platform_key, maskedcredentials(e.g.sup****key), maskedextra_headers,connected_service_summary({id, provider, service, user, platform_key}). - GET
…/users/{username}/mentors/{mentor}/settings/— the agent's activetool_slugs,mcp_servers(serialized server objects), andcan_use_tools. - GET
https://api.iblai.app/dm/api/ai-account/orgs/{org}/oauth-services/— enabled OAuth services:id,oauth_provider,name,display_name,description,scope,image,created_at,updated_at. - GET
https://api.iblai.app/dm/api/ai-account/orgs/{org}/oauth-services/{service_name}/scopes/— the scopes a service requests. - GET
https://api.iblai.app/dm/api/ai-account/connected-services/orgs/{org}/users/{username}/— the user's connected services (token grants). - GET
https://api.iblai.app/dm/api/ai-account/connected-services/orgs/{org}/users/{username}/{provider}/{service}/— start an OAuth flow; returns{ "auth_url": "..." }. The state entry it primes expires after 1 hour. - GET
https://api.iblai.app/dm/api/ai-account/connected-services/callback/?code=...&state=...— the OAuth callback. Hit by the user's browser after provider consent — relay the vendor's query params unmodified (never decode or alterstate); do not call it directly with fabricated values. Success returns the connected service (id,provider,service,expires_at,scope(raw scope string),scope_names(canonical ids, e.g.["drive"]),scopes(full scope strings),token_type,service_info({id, name, display_name, logo}),username) — the sameConnectedServiceSerializerthe connected-services list read returns.
Writes
MCP servers
- POST
…/users/{username}/mcp-servers/— register a server (JSON, ormultipart/form-datawithimage):{ "name": "Google Drive MCP", "url": "https://drive-mcp.example.com", "transport": "sse|websocket|streamable_http", "auth_type": "none|token|oauth2", "auth_scope": "platform|mentor|user", "description": "string", "mentor": "uuid|null", "credentials": "string", "extra_headers": { "x-custom": "value" }, "oauth_service": "number|null", "is_enabled": true, "is_featured": false, "clean_output": true, "image": "File" }name,url,transport,auth_typeare required;auth_scopedefaults toplatform.- Server-level
credentialsmust be the full authorization value (<scheme> <credentials>); it takes priority overextra_headers. is_featured=truemakes the server available to other orgs to create their own connections against (multi-tenant sharing); the owning org keeps control of the metadata.is_enabled=falseis a hard off-switch — disabled servers are skipped at runtime.oauth_servicelinks the OAuth service and is required for in-chat OAuth servers.clean_output(default true) strips HTML from server responses; disable it for documentation servers whose formatting must survive.- Capture the returned
id— the connection and the agent wiring both need it.
- PATCH | PUT
…/users/{username}/mcp-servers/{id}/— edit a server (e.g. flip an existing server to in-chat OAuth with{"auth_scope": "user", "auth_type": "oauth2", "oauth_service": 12}). - DELETE
…/users/{username}/mcp-servers/{id}/— delete a server. Destructive — confirm with the user first.
MCP server connections
-
POST
…/users/{username}/mcp-server-connections/— create a connection. Common fields:server(id, required),scope(platform|mentor|user, defaultuser),auth_type(none|token|oauth2),credentials,authorization_scheme,extra_headers,connected_service(id),mentor(agent unique id).Platform scope (token):
{ "server": 9, "scope": "platform", "auth_type": "token", "credentials": "super-secret-api-key", "authorization_scheme": "Bearer", "extra_headers": { "x-mcp-client": "agent-ui" } }Mentor (agent) scope (token): add
"mentor": "<agent unique id>"and"scope": "mentor"— different agents can present different credentials to the same server (e.g. read/write vs read-only keys).User scope (OAuth2) — finalizes an OAuth connection after the connected-service flow:
{ "server": 9, "scope": "user", "auth_type": "oauth2", "connected_service": 77 }Validation rules the API enforces (per-field error messages):
platformanduserare read-only: the org comes from the request context ("Connections must be created for the current platform context."when they clash) and the user from the caller — do not send them in the body.scope=platform—mentoris forbidden; the connection's org must match the server's org unless the server is featured.scope=mentor—mentoris required and must belong to the same org as the connection.scope=user—mentoris forbidden; requires the calling user or aconnected_service.auth_type=oauth2— always requiresconnected_service("OAuth2 connections require a connected service."), at every scope, and the connected service must belong to the same org.auth_type=token— requirescredentials("Token based connections must include credentials.").
Credential handling:
authorization_schemebecomes the header prefix (Authorization: Bearer <credentials>); omit it to send the raw value.extra_headersis merged into every outbound request; explicit credentials override clashing headers.credentialsandextra_headersare masked on read — when PATCHing, only sendcredentialsif actually rotating the secret; never send a masked value back.
-
PATCH
…/users/{username}/mcp-server-connections/{id}/— update; prefer{"is_active": false}over DELETE if the credential may return. -
DELETE
…/users/{username}/mcp-server-connections/{id}/— delete a connection. Destructive — confirm with the user first.
Agent wiring
- PATCH | PUT
…/users/{username}/mentors/{mentor}/settings/— enable / disable connectors on the agent:
Critical semantics — these lists are replaced, not merged.{ "tool_slugs": ["ai-index", "mcp-tool"], "mcp_servers": [3, 9], "can_use_tools": true }[]clears everything; omitting a field leaves it untouched. Blindly sending{"tool_slugs": ["mcp-tool"]}silently strips every other tool the agent had. Safe procedure: GET the current settings, merge locally (keep existingtool_slugs, ensuremcp-toolis present; keep existingmcp_servers, append the new server id), then write back the full lists.
OAuth connected services
- DELETE
https://api.iblai.app/dm/api/ai-account/connected-services/orgs/{org}/users/{username}/{id}/— revoke a user's OAuth grant / disconnect the service (204). Destructive — confirm with the user first.
In-chat OAuth (per-user consent at chat time)
For servers with auth_type="oauth2" + auth_scope="user", the platform
prompts each user inside the chat stream the first time the agent needs the
tool. Events arrive as JSON on the existing chat WebSocket/SSE
connection — parse and switch on type; never close or refresh the
connection while waiting, resolution arrives on the same socket.
Trigger conditions (all must hold): server auth_type="oauth2", server
auth_scope="user", no valid connection for the current user + server, and
the chat user is authenticated (non-anonymous).
Admin setup checklist (before any prompt can fire): the OAuth provider
and OAuth service records exist, the auth_{provider} credential is in the
org's credential store, the MCP server is registered with
auth_type="oauth2", auth_scope="user", is_enabled=true, and a linked
oauth_service, and the server is attached to the agent (tool_slugs +
mcp_servers).
Handshake: the user sends a message → the backend fails to resolve a
user connection → it emits oauth_required (with auth_url) and polls
every 10s → the client opens auth_url; the user consents; the backend
callback creates the connected service + connection automatically (the
client does not process the callback) → the backend emits
oauth_connection_resolved and resumes the turn. On timeout (default 300s)
an error (status 400) terminates the turn — on WebSocket transports the
connection then closes. A user who finishes OAuth after the timeout
succeeds automatically on their next message, so offer a retry.
Event reference:
Event type | Key fields | Client action |
|---|---|---|
oauth_required | server_name, server_id, auth_url, message | show a prompt naming the server; open auth_url in a new tab; show a waiting indicator |
oauth_connection_resolved | server_name, server_id, message | dismiss the prompt; the chat resumes automatically |
mcp_tools_retrieved | session_id, mentor_id | informational: tool fetch succeeded on retry (3 attempts, backoff 1s/2s/4s) — log or ignore |
warning | message, developer_error, code: 503 | non-OAuth tool failure; the chat continues without MCP tools — surface message, log developer_error, never show it to end users |
error | error, status_code: 400 (no type field — detect by the top-level error key) | OAuth timeout / URL build failure / missing connected service; the turn terminates — offer retry |
Constants: max wait 300s (MCP_OAUTH_MAX_WAIT_SECONDS), poll interval 10s
(MCP_OAUTH_POLL_INTERVAL_SECONDS). Each poll checks for a connection with a
valid connected service for user + server (or a connected service matching
provider + user + org) — first match resolves.
Example
Register a platform-token server, bind the shared key, and enable it on an agent (settings read-merge-write elided):
BASE="https://api.iblai.app/dm/api/ai-mentor/orgs/$IBLAI_ORG/users/$IBLAI_USERNAME"
AUTH="Authorization: Api-Token $IBLAI_API_KEY"
curl -s -X POST "$BASE/mcp-servers/" -H "$AUTH" -H "Content-Type: application/json" \
-d '{"name":"Workflow MCP","url":"https://wf.example.com/mcp","transport":"streamable_http",
"auth_type":"token","auth_scope":"platform","is_enabled":true}'
# → capture "id": 9
curl -s -X POST "$BASE/mcp-server-connections/" -H "$AUTH" -H "Content-Type: application/json" \
-d "{\"server\":9,\"scope\":\"platform\",\"auth_type\":\"token\",
\"credentials\":\"$MCP_KEY\",\"authorization_scheme\":\"Bearer\"}"
Notes
- Troubleshooting quick map:
400 OAuth2 connections require a connected service.— complete the connected-service flow first; pass the resulting id.400cross-org server on a platform connection — use a server owned by this org, or mark the source serveris_featured=true.400 No credentials foundon OAuth start — install theauth_{provider}credential (client_id, client_secret, redirect_uri).- Agent never calls the server —
mcp-toolmissing fromtool_slugsor the server id missing frommcp_servers; these lists are replaced, not merged, so a careless settings write may have stripped them. - No OAuth prompt on a per-user server — needs both
auth_scope="user"andauth_type="oauth2", plus a linkedoauth_service, plus an authenticated (non-anonymous) chat session. - Prompt fires every message even after auth — the connected service belongs to a different user or org than the chat user.
- Connection unexpectedly falls back to platform creds — check the user
connection's
is_activeand that the connected service's user matches the chat user. oauth-servicesreturns[]— no enabled OAuth service records; seed the provider + service.- Callback
Invalid state— the start/callback round-trip spanned browser contexts or exceeded the 1-hour window; redo the flow in one session. - Callback
Could not exchange auth token— the provider rejected the code; verify the redirect URI matches the provider console and restart. - Tool call fails silently — a
warning(503) event was ignored; surface it and verify the MCP server is reachable from the platform.
- Scope enum is
platform | mentor | useron bothMCPServer.auth_scopeand connectionscope—mentormeans agent-wide,platformmeans org-wide. (There is noagentortenantvalue on the wire.) - The chat events above ride the runtime chat connection (see
/iblai-api-agent-chatfor wiring live chat); everything else in this skill is plain REST.
Reference material
references/ carries the additive material that doesn't fit the endpoint
sections above — the endpoint/method/body and event facts stay above:
references/concepts.md— backend model and the design "why": the five Django models behind the wire objects, the module map, runtime-resolution internals, the OAuth state/token design, and the validation, access-control, and extensibility rules.references/integration.md— client / front-end notes for the REST setup screens: driving the connection form offauth_type, scope-aware fields, sourcing the OAuth2 connected-service picker, rendering inline per-field validation errors, and the browser OAuth start/callback strategy.references/in-chat-events.md— the fuller per-frame event reference: field types, the threeerrorvariants with their exact messages, and the client-handling gotchas.references/mcp-servers-catalog.md— the open-sourceiblai-mcprepo of ready-made MCP servers. This skill wires external MCP servers onto agents; that repo is a source of servers to wire.
What ships with it: 4 files
12.6 KB alongside SKILL.md
references/
- concepts.md4.8 KB
- in-chat-events.md3.3 KB
- integration.md3.4 KB
- mcp-servers-catalog.md1.1 KB