Install
$ agentstack add skill-sensein-agent-skills-brainkb ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ● Filesystem access Used
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
BrainKB Skills
This skill provides tools for ingesting, querying, and exploring BrainKB (Brain Knowledgebase).
Every BrainKB operation goes through the brainkb_* MCP tools. There is no fallback. If a tool errors, read the error and fix the cause — do not reach for curl, a shell script, a different MCP server, or a direct HTTP call to queryservice/usermanagement. Those paths bypass the identity the MCP holds, so they either fail differently or succeed under the wrong attribution, and a mutation attributed to the wrong caller cannot be undone. The only curl in this document is the operator's deployment health check at the end, run on the deploy host by a human, and it is not an agent fallback.
Connectivity — READ FIRST
There are two ways to reach BrainKB, and the right one depends on where this code runs:
- Hosted remote —
https://mcp.brainkb.org/mcp(live). Works from anywhere,
including cloud/sandbox sessions. Register it once: ``bash claude mcp add --scope user --transport http brainkb https://mcp.brainkb.org/mcp ` The operator has already configured the backend, so **do not pass base_url** to any tool here — see the allowlist note under *Credentials & safety*. Authenticate per caller (PAT via Authorization: Bearer`, or the login tools).
- Local stdio MCP →
http://localhost:8010. Only works when the caller runs on
the same machine as the BrainKB Docker stack, through the local MCP process. A cloud/sandbox session cannot reach a localhost deployment on the user's laptop and no base URL will fix that — use the hosted remote instead.
Two notes on diagnosing failures:
- A connection error / HTTP 000 / connection refused means the caller can't
reach the deployment — don't keep guessing URLs. For the local path, check the MCP is running and the stack is up (http://localhost:8010/openapi.json → 200 on that machine). Ask the user rather than retrying different hosts.
GET https://mcp.brainkb.org/mcpin a browser returns **406 "Client must accept
text/event-stream"**. That is the endpoint working, not an outage; / serves a plain landing page and /healthz returns ok.
Do not fall back to curl, a local script, or another MCP server from any session — use the hosted remote's MCP tools, or stop and report what is blocking.
Rate limits apply on the hosted remote (per caller IP): roughly 8 logins, 40 writes/ingests, 120 reads and 30 admin calls per minute. A limited call returns status_code: 429 with a detail naming the bucket — surface it and wait out the window. Never retry-loop, and never split one job into many calls to get around it.
Credentials & safety
- **How to authenticate — pick in this order. Do NOT ask the user for a password
by default; BrainKB is a Globus/OAuth-first system and password login is being retired.**
- Already configured? On the hosted remote each caller authenticates via an
Authorization: Bearer header, or a BRAINKB_TOKEN (PAT) set in the MCP config — in that case no login step is needed at all. Check with brainkb_whoami() before asking for anything.
- Personal Access Token (PAT) — the recommended browser-free credential.
If the user has one, brainkb_use_token("brainkb_pat_…") (or they set it as BRAINKB_TOKEN). If they don't, mint one after step 3 with brainkb_create_token(name, days).
- Globus / ORCID / GitHub (browser) — the normal way to sign in as a real
user. Call brainkb_globus_login(); it returns a URL for the user to open, they sign in, the browser shows a short code, and you finish with brainkb_finish_login(""). This is what you should do when the user says "log in as " — start the Globus flow, do not ask for a password.
- Password (legacy, discouraged) — only if the user explicitly has a
password account and asks to use it: brainkb_login(email, password). Never volunteer this path or prompt for a password unprompted.
- Base URL: on the hosted remote it is fixed by the operator — omit
base_url
entirely. For a local stdio MCP the default is http://localhost:8010; ask only if it isn't already set and the user hasn't said where the deployment is.
- Never print, echo, or store the password or the JWT token. Pass them straight
to the login step, and keep them out of chat — in the operator's shell snippets read them from an environment variable, never inline. (The one exception is the PAT returned by brainkb_create_token, shown to the user once so they can copy it into their config — never re-display it afterward.)
- A PAT is revocable instantly (
brainkb_revoke_token) and its roles are
re-checked live on every use, so a ban/demotion takes effect at once.
- Identity must be verified, never assumed — this is the #1 correctness rule.
Mutations (create space, ingest, add member, grant) are attributed to the authenticated identity permanently (provenance records who did what). A login step reporting "Logged in as X" is not proof the next call runs as X: the MCP silently falls back to a configured BRAINKB_EMAIL/BRAINKB_PASSWORD, BRAINKB_TOKEN, or an Authorization header when the session login isn't carried forward (common on the hosted streamable-http transport). So:
- After every login, call
brainkb_whoami()and confirmemail== the
intended user.
- Immediately before any write/mutation, call
brainkb_whoami()again and
confirm it still matches. Only proceed if it does.
- If it shows a different/unexpected account (e.g. a shared
test@…),
STOP — report the mismatch, don't write. The durable fix is a per-call credential that can't be shadowed: a PAT (BRAINKB_TOKEN / brainkb_use_token) or an Authorization: Bearer header. A leftover BRAINKB_EMAIL/BRAINKB_PASSWORD in the MCP config is the usual culprit and should be removed on a shared/multi-user MCP.
- Confirm before mutating actions (creating a space, ingesting, changing
visibility, adding members). Reads are safe.
- Authorization is role-based, not just JWT (see the section below). A
403
usually means the user's role/capability (or a space access rule) doesn't permit the action — not that the API token is invalid. Explain which role/capability is needed and that an Admin can grant it.
Core concepts (so you pick the right call)
- Space = an owner-controlled workspace containing named graphs, with
visibility = private (members only) or public (anyone, even without logging in, can read). Two space_types: individual (a personal space) and team (shared). Ingest into a graph requires owner/editor membership of its space and the ingest capability.
- Roles govern what a user may do (JWT is only API access). Roles come from the
user's account; they map to capabilities like create-space / ingest / admin.
- Ingestion is submit-and-forget: it returns a
job_idand runs in the
background. Always poll job status rather than assuming it finished.
- Provenance lives natively in the graph DB (PROV-O). Every ingest is an
activity; each job's added triples are a queryable delta.
- A SynthScholar review reaches BrainKB by being ingested, like any other RDF.
The synthscholar skill runs the review and writes review.ttl; a user with write access ingests it here, into the graph https://brainkb.org/synthscholar/reviews// bound to a space. Going through the ingest pipeline is what gives the review a job, PROV-O provenance and a search index. See "Ingest a SynthScholar review".
Authorization (roles & capabilities)
Who can do what is decided by the user's role → capability, then space membership, then any per-space access rule. Key rules to set expectations:
- Create a team space: Admin/SuperAdmin only — or a user an admin has granted
create_team_space. Use space_type="team".
- Create an individual/private space: any write-capable role (Curator, Lab
Member, Submitter, Annotator, Mapper, Knowledge Contributor, Admin). Default space_type="individual".
- Ingest / recover: write-capable role (+ owner/editor of the space).
- Arbitrary SPARQL: Admin/SuperAdmin only.
- No role: read public content only — cannot create/ingest/read private.
- Delegated upgrades (Admin only):
brainkb_grant_capability(member, capability)
— e.g. let a Lab Member create team spaces. Inspect with brainkb_capabilities(member). Admin-only caps (grant, sparql_admin) are not delegatable.
- Fine-grained per-space rules: within a space, restrict an action to a role /
member / space-role (see "Manage & delegate"). Owner + Admin always bypass.
If an action is denied, check the user's roles/capabilities (brainkb_capabilities) and either ask an Admin to grant the needed capability, or adjust the space's access rules.
Workflows
0. Register a new account (no login needed)
For password-based signup: brainkb_register(full_name, email, password). This creates the credential and a canonical profile with a default Curator role, so the user is a first-class identity. The account starts inactive — an Admin/SuperAdmin must activate it (see §9) before login works. (Alternatively, users can onboard by first login via Globus/ORCID/GitHub, which auto-provisions the same profile + default role.) Never echo the password back.
1. Log in
Auth order (TL;DR) — take the first that applies:
brainkb_whoami()→ ifauthenticated: true(a PAT/header is already
configured), stop, you're done.
- User has a PAT →
brainkb_use_token("brainkb_pat_…")(or it's set as
BRAINKB_TOKEN). Best for repeated use — survives across calls, no browser.
- Need to sign in as an account → Globus (
brainkb_globus_login→
brainkb_finish_login). Then mint a PAT (brainkb_create_token) so future sessions skip the browser.
- Password (
brainkb_login) → only if the user explicitly has one. Never
prompt for a password on your own. Always brainkb_whoami() again after logging in to confirm the identity stuck (see the ⚠️ box below). PAT/header = per-call identity (reliable); in-session login can evaporate on the hosted remote.
Local (stdio) vs hosted remote — how the PAT is passed:
- Local/stdio: put the PAT in
BRAINKB_TOKEN(config env). Simple, single-user. - Hosted remote (
mcp.brainkb.org, streamable-http): each caller sends their
PAT as an Authorization: Bearer header — a baked-in BRAINKB_TOKEN is ignored there (it would make every anonymous caller act as one shared identity) unless the operator sets MCP_ALLOW_SHARED_IDENTITY. So on the remote it's per-caller header, not a shared env token.
- The backend URL is allowlisted (
MCP_ALLOWED_BASE_URLS):base_url/
X-BrainKB-Base-URL can only point at pre-approved backends (that URL is where credentials are sent). An unknown base URL is refused — don't try to work around it by guessing hosts.
First run brainkb_whoami() — if it already reports authenticated: true (header token or BRAINKB_TOKEN PAT is configured), you're done; don't ask for anything.
If it reports authenticated: false, do NOT stop and offer the user a menu of auth methods. Immediately call brainkb_globus_login() and hand over the URL it returns — that is the only path that works from a cold start, so presenting it as a choice just adds a round trip. Then take the code they paste, brainkb_finish_login(""), and mint a PAT in the same turn with brainkb_create_token(name="laptop", days=90) so the next session doesn't repeat any of this. Only ask the user something if they offer a PAT, or if the login itself fails.
Two things not to say while doing it:
- Don't read
base_urlas the user's own machine. It is the server's backend,
not what the client connected to. On the hosted remote it reads http://host.docker.internal:8010 — that is the MCP's co-located stack inside the deployment, and it is correct. Never tell the user they're "pointed at a local stack" or that their PAT might be for the wrong backend because of it.
- Don't warn that an in-session login "won't stick" before trying. Within one
session it persists; it just doesn't carry into the next session — which is what minting the PAT solves.
For reference, the methods in preference order — default to Globus, never prompt for a password unprompted:
- Globus / ORCID / GitHub (browser) — the default for "log in as ":
brainkb_globus_login()(orbrainkb_globus_login("orcid")/("github"))
→ returns a URL; give it to the user to open and sign in.
- The browser then shows a short one-time code — ask the user to paste it.
brainkb_finish_login("")→ completes login for this session.
The browser sign-in is unavoidable (only the user can consent at the provider), but the rest stays in the skill. First OAuth login auto-creates/links the profile + a default Curator role. When a user asks to sign in as a specific account and no PAT/header is configured, start THIS flow — do not ask for a password.
- Personal Access Token (PAT) — recommended for repeated use, no browser:
brainkb_use_token("brainkb_pat_…")if the user already has one — done.- To mint one: log in once (Globus, above), then
brainkb_create_token(name="laptop", days=3) → returns a brainkb_pat_… token once. Give it to the user to copy.
- The user sets it as
BRAINKB_TOKENin the MCP config (or calls
brainkb_use_token("") per session). No login/browser afterward until it expires (default 3 days; pass days up to the server cap for longer).
- Manage:
brainkb_list_tokens()(metadata only),brainkb_revoke_token(id)
(instant). PATs are the cleanest way to avoid re-authenticating every session.
- Password (legacy, discouraged — being retired):
brainkb_login(email, password, base_url?). Use only if the user explicitly says they have a password account and want to use it. Never prompt for a password otherwise.
> ⚠️ ALWAYS verify identity after logging in — do not trust the login message. > Immediately after brainkb_finish_login / brainkb_login / brainkb_use_token, > call brainkb_whoami() and confirm the returned email is the account you > intended. A login step can report "Logged in as X" yet subsequent calls run as a > different account — because the MCP falls back, silently, to a configured > BRAINKB_EMAIL/BRAINKB_PASSWORD (or BRAINKB_TOKEN, or an Authorization > header) when the just-established session isn't carried into the next call (this > is common on the hosted streamable-http transport, where per-session login may > not persist between tool calls). If whoami shows a different or unexpected > account, STOP — the login did not take effect. Do NOT create/ingest/mutate > (see the identity rule in "Credentials & safety"). The reliable fix is a > per-call credential that can't be shadowed: a PAT via BRAINKB_TOKEN / > brainkb_use_token, or an Authorization: Bearer header — not an in-memory > session login on a multi-user remote.
Troubleshooting login/auth (common failures):
brainkb_globus_login→ the browser ends on…?error=unauthorized_client.
The Globus app is the wrong type: it must be a "Portal / application you host" (confidential OAuth client), NOT a "Service API" app. A Service-API app can't run the login (authorization-code) flow, so Globus rejects it. Fix is server-side (register a Portal-type app); as the agent, tell the user this rather than retrying — a new code won't help.
…?error=…redirect… mismatch/ "Mismatching redirect URI". The backend's
`USERMANAGEMENT_PUBLI
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sensein
- Source: sensein/agent_skills
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.