Developers
Connect an agent to your team’s Skills Board.
The MCP endpoint, the OAuth flow, and the discovery documents an agent reads before it connects, with the versioning, error, and rate-limit conventions the whole surface follows.
Skills Board is a web app for the AI skills a team recommends, and its programmatic surface is a Model Context Protocol server. An agent that authenticates against it can search the team's saved skills and collections, fetch install commands, inspect a GitHub repository for skills, and, with write access, save skills and organize collections.
This page is the whole contract: what is public, how to authenticate, what the tools do, and how the surface behaves when something goes wrong. Everything on it is also machine readable: append .md to this URL, or send Accept: text/markdown, for the same document as Markdown.
The public surface
Everything below is public and needs no credential to fetch, except the MCP endpoint itself. Anything under /api that is not listed here backs the web UI on a session cookie and is not an integration point: it can change without notice.
| Endpoint | What it is | Authentication |
|---|---|---|
| /api/mcp | The MCP server. JSON-RPC 2.0 over streamable HTTP. | Bearer token, user-delegated |
| /api/health | Liveness of the deployment. Backing services are not probed. | None |
| /openapi.json | OpenAPI 3.1 description of everything in this table. | None |
| /server.json | MCP registry manifest: identity, version, and the remote endpoint. | None |
| /.well-known/mcp/server-card.json | MCP Server Card (SEP-1649): transport, capabilities, tools, and scopes. The same card answers at /.well-known/mcp. | None |
| /.well-known/oauth-protected-resource | RFC 9728 metadata: the audience a token must be bound to. | None |
| /.well-known/api-catalog | RFC 9727 linkset naming this API and its documents. | None |
| /.well-known/ai-catalog.json | Agentic Resource Discovery manifest for this origin. | None |
| /.well-known/agent-skills/index.json | The Agent Skills this site publishes, each with a sha256 digest. | None |
Connect an agent
Any MCP client that speaks streamable HTTP and can run an OAuth authorization code flow connects without a manually issued key: the server registers the client itself (RFC 7591) the first time it asks.
- Point the client at https://www.skillsboard.sh/api/mcp as a streamable HTTP MCP server.
- Let the client discover authentication: an unauthenticated call answers 401 with a WWW-Authenticate header naming the protected resource metadata.
- The client registers itself dynamically, then runs authorization code + PKCE. A person approves the scopes in a browser; nothing is issued without that approval.
- Call
tools/liston the live session for the tool schemas, thentools/call.
{
"mcpServers": {
"skills-board": {
"type": "http",
"url": "https://www.skillsboard.sh/api/mcp"
}
}
}The client identifier the registry knows this server by is io.github.TommyBez/skillsboard. A client that cannot run the flow itself can still read every discovery document above, none of which needs a credential.
Tools
The live session is the source of truth for tool schemas; this is the list and what each one needs. A tool marked skills:write is refused by a token that was granted read access only.
| Tool | What it does | Scopes |
|---|---|---|
| list_skills | List every skill saved across the authenticated user's team libraries | skills:read |
| search_skills | Search saved team skills by name, description, note, example prompt, repository, or tag | skills:read |
| get_skill_command | Return the skills.sh CLI command for a saved skill | skills:read |
| discover_skills | Search skills.sh or browse a leaderboard | skills:read |
| discover_repository_skills | List the installable skills (SKILL.md definitions) found in a GitHub repository, with the skillPath to use when saving one | skills:read |
| add_skill | Save a skill from a GitHub repository to a team library. When the repository contains multiple skills, use discover_repository_skills first and pass the chosen skillPath. | skills:read, skills:write |
| list_collections | List every skill collection across the authenticated user's team libraries, with skill counts | skills:read |
| search_collections | Search team skill collections by title, description, or tag | skills:read |
| get_collection_skills | List the skills grouped in a collection, with their install commands | skills:read |
| get_collection_install_command | Get the one-command installer for a published installable collection | skills:read |
| create_collection | Create a team collection that groups saved skills by use case or project. Collections are visible to the whole team. | skills:read, skills:write |
| add_skill_to_collection | Add a saved team skill to a collection. Use list_skills and list_collections to find the IDs. | skills:read, skills:write |
| remove_skill_from_collection | Remove a skill from a collection. The skill stays in the team library. | skills:read, skills:write |
Authentication and scopes
Access is user-delegated: a token acts for the person who approved it and reaches exactly the team libraries they belong to. Tokens are audience-bound to the MCP endpoint, so a token minted for another resource is refused.
| Scope | What it grants |
|---|---|
| openid | Confirm your Skills Board identity |
| profile | View your name and basic profile |
| View your email address | |
| offline_access | Keep access after you close the client |
| skills:read | View and search saved skills, collections, public skills, and install commands |
| skills:write | Save new skills and organize collections in your team libraries |
Revoking a client in Skills Board invalidates its tokens immediately; the next call answers 401 and the client is expected to run the flow again rather than retry.
The registration, authorization, and revocation flow, written for an agent to follow step by step: auth.md.
Versioning and deprecation
The current version of the HTTP surface is 1. Every response carries it in Skills-Board-Api-Version, and a request may send the same header to pin the version it was written against. Supported today: 1. A pinned version this deployment does not serve is refused with 400 and the unsupported_api_version problem rather than answered with a different one.
The paths are deliberately unversioned. The MCP endpoint is the audience every issued token is bound to, and the well-known documents live where their specifications put them; moving either into a /v1 prefix would invalidate tokens and break spec-driven discovery. The version travels in the header instead.
Within a version, members are added but never removed or retyped, and a tool never changes what it does under the same name. A breaking change ships as the next version, and both versions answer until the older one is withdrawn.
A withdrawal is announced on the affected responses with Deprecation and Sunset headers at least 90 days before the sunset date, and the same dates appear on this page. Nothing is removed without that notice.
Deprecation policy
Nothing in the table above is withdrawn without notice. When an operation, a member, or a header is going away, every response it still serves carries Deprecation (RFC 9745) with the date the withdrawal was announced and Sunset (RFC 8594) with the date it stops answering.
The gap between those two dates is never less than 90 days. Until the sunset date the operation answers normally; after it, the path is gone and a request to it gets the ordinary 404.
A client that wants to be warned early should read both headers on every response and treat their appearance as work to schedule, not as an error. The same policy is stated in the OpenAPI description under info.x-deprecation-policy, which names this section, the notice period, and the two headers.
Errors
Failures are typed, and the type is what a client should branch on. The MCP endpoint reports failures the way JSON-RPC does, including 401 and 403, which carry a JSON-RPC error object with a numeric code. Every other endpoint answers with an RFC 9457 problem document under application/problem+json.
HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 37
RateLimit: "public";r=0;t=37
{
"type": "https://www.skillsboard.sh/developers#error-rate-limited",
"title": "Too many requests",
"status": 429,
"detail": "This client has spent its request budget for the current window. Wait for the window named in Retry-After, then retry.",
"instance": "https://www.skillsboard.sh/api/health",
"code": "rate_limited",
"retry_after": 37
}The type member is a URL that resolves to the section of this page describing that failure, so a client meeting an unfamiliar code can fetch the explanation instead of parsing the prose. title and detail are written for people and may be reworded; code and status are the stable pair.
The MCP endpoint never answers with a problem document, including for the two refusals it makes before a request reaches the protocol: a pinned version it does not serve (400) and a spent budget (429). Both come back as JSON-RPC error objects, because that is the one body shape an MCP client parses, and both carry the same code from the table above in error.data.code, with retry_after beside it on a 429.
rate_limited
429 Too many requests. This client has spent its request budget for the current window. Wait for the window named in Retry-After, then retry.
unsupported_api_version
400 Unsupported API version. The Skills-Board-Api-Version header named a version this deployment does not serve. Omit the header to get the current version.
Rate limits
The budgeted endpoints publish what a client has left. The policy is 120 requests per 60 seconds per client per endpoint, and 600 per 60 seconds on the MCP endpoint, counted over a sliding window.
It is counted per serving instance rather than globally, so the numbers are a floor: a client that stays inside them is never refused, and a client spread across instances may get more. That is the honest reading of the headers, and it is the reading an agent needs to pace itself.
A refused request answers 429 with Retry-After. Retrying before the window rolls over is refused again, and the refusal is not charged to the budget.
Clients are counted by the address the platform reports. A request that arrives without one is not counted against anybody, and its response states the policy without a remaining count rather than pooling every such caller into one bucket they could spend for each other.
The discovery documents are served from cache and carry no budget.
| Header | What it says |
|---|---|
| RateLimit | Remaining requests (r) and seconds until the window rolls over (t). |
| RateLimit-Policy | The quota in force: requests (q) per window seconds (w). |
| RateLimit-Limit / -Remaining / -Reset | The same three numbers in the older spelling most SDKs already parse. |
| Retry-After | On a 429 only: seconds to wait before retrying. |
Markdown, for reading rather than parsing
Every public page on this site has a Markdown twin at the same URL with a .md suffix, and the page URL itself returns Markdown when the request sends Accept: text/markdown. Those responses carry an x-markdown-tokens header estimating the document's size, so a client can budget a read before it makes it.
Start at https://www.skillsboard.sh/llms.txt, which indexes every page, document, and endpoint this site publishes.
Status, support, and source
- Deployment liveness: HTTP liveness of this deployment. Backing services are not probed.
- Open an issue: Bugs, integration questions, and requests for the MCP surface.
- Source: The whole app, MIT licensed, including every endpoint on this page.
- Contact: For anything that does not belong in a public issue.