Iblai api agent mcp
Agent skills + a chat MCP server to operate the ibl.ai platform via its REST API. Install: npx skills add iblai/api
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.
One thing to look at
- 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.
What its author says it does
Copied from the file, not written here
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.
SKILL.md
19.7 KB, 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.