agentsclimarketplace

Iblai api agent mcp

Skill iblai/api/skills/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

Install
npx -y skills add iblai/api --skill iblai-api-agent-mcp

Assembled 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:

  1. MCP server — metadata for the external MCP endpoint (name, URL, transport, auth_type, auth_scope).
  2. MCP server connection — the credential binding (a static token, or a reference to an OAuth connected service), at platform, mentor (agent), or user scope.
  3. Agent wiring — the agent's settings must have the mcp-tool slug in tool_slugs AND the server id in mcp_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 /dm prefix 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 abbreviates https://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/ for mentors/); the mentor spelling is canonical and used here, matching the other skills.
  • Header: Authorization: Api-Token $IBLAI_API_KEY on 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 value mentor refer 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-login first to populate IBLAI_ORG, IBLAI_USERNAME, and IBLAI_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.

PatternServer fieldsConnection setupEnd user prompted?
No authauth_type=noneconnection with no credentialsNo
Shared key for the whole orgauth_type=token, auth_scope=platformone platform-scoped connection holding the keyNo
Per-agent keyauth_type=token, auth_scope=mentorone mentor-scoped connection per agentNo
Pre-provisioned per-userauth_scope=useradmin creates user-scoped connections up frontNo
In-chat OAuth (each user connects their own account)auth_type=oauth2 and auth_scope=usernone up front — created automatically when the user completes OAuth mid-chatYes

Facts to keep straight:

  • auth_type="oauth2" + auth_scope="user" is the only combination that triggers the in-chat OAuth prompt; oauth2 alone is not enough.
  • Any oauth2 connection (at any scope) requires a connected_service id — 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:

  1. User-scoped connection for (server, user)
  2. Mentor-scoped connection for (server, agent)
  3. Platform-scoped connection for (server, org)
  4. Featured-server global fallback
  5. 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=true surfaces org-wide connectors; search and transport narrow results).
  • GET …/users/{username}/mcp-server-connections/ — list connections: scope, is_active, server_name, platform_key, masked credentials (e.g. sup****key), masked extra_headers, connected_service_summary ({id, provider, service, user, platform_key}).
  • GET …/users/{username}/mentors/{mentor}/settings/ — the agent's active tool_slugs, mcp_servers (serialized server objects), and can_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 alter state); 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 same ConnectedServiceSerializer the connected-services list read returns.

Writes

MCP servers

  • POST …/users/{username}/mcp-servers/ — register a server (JSON, or multipart/form-data with image):
    {
      "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_type are required; auth_scope defaults to platform.
    • Server-level credentials must be the full authorization value (<scheme> <credentials>); it takes priority over extra_headers.
    • is_featured=true makes 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=false is a hard off-switch — disabled servers are skipped at runtime.
    • oauth_service links 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, default user), 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):

    • platform and user are 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=platformmentor is forbidden; the connection's org must match the server's org unless the server is featured.
    • scope=mentormentor is required and must belong to the same org as the connection.
    • scope=usermentor is forbidden; requires the calling user or a connected_service.
    • auth_type=oauth2 — always requires connected_service ("OAuth2 connections require a connected service."), at every scope, and the connected service must belong to the same org.
    • auth_type=token — requires credentials ("Token based connections must include credentials.").

    Credential handling:

    • authorization_scheme becomes the header prefix (Authorization: Bearer <credentials>); omit it to send the raw value.
    • extra_headers is merged into every outbound request; explicit credentials override clashing headers.
    • credentials and extra_headers are masked on read — when PATCHing, only send credentials if 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:
    { "tool_slugs": ["ai-index", "mcp-tool"], "mcp_servers": [3, 9],
      "can_use_tools": true }
    
    Critical semantics — these lists are replaced, not merged. [] 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 existing tool_slugs, ensure mcp-tool is present; keep existing mcp_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 typeKey fieldsClient action
oauth_requiredserver_name, server_id, auth_url, messageshow a prompt naming the server; open auth_url in a new tab; show a waiting indicator
oauth_connection_resolvedserver_name, server_id, messagedismiss the prompt; the chat resumes automatically
mcp_tools_retrievedsession_id, mentor_idinformational: tool fetch succeeded on retry (3 attempts, backoff 1s/2s/4s) — log or ignore
warningmessage, developer_error, code: 503non-OAuth tool failure; the chat continues without MCP tools — surface message, log developer_error, never show it to end users
errorerror, 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.
    • 400 cross-org server on a platform connection — use a server owned by this org, or mark the source server is_featured=true.
    • 400 No credentials found on OAuth start — install the auth_{provider} credential (client_id, client_secret, redirect_uri).
    • Agent never calls the server — mcp-tool missing from tool_slugs or the server id missing from mcp_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" and auth_type="oauth2", plus a linked oauth_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_active and that the connected service's user matches the chat user.
    • oauth-services returns [] — 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 | user on both MCPServer.auth_scope and connection scopementor means agent-wide, platform means org-wide. (There is no agent or tenant value on the wire.)
  • The chat events above ride the runtime chat connection (see /iblai-api-agent-chat for 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 off auth_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 three error variants with their exact messages, and the client-handling gotchas.
  • references/mcp-servers-catalog.md — the open-source iblai-mcp repo 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

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.