# Skill Router — connect your agent Skill Router is this organization's library of **skills**: written instructions for doing a particular kind of work the way the organization does it. It is an MCP server. Once connected, an agent can list, search and pull skills, report how they were used, and propose edits. - **MCP endpoint:** `https://skills.sidekick.systems/mcp` - **Transport:** Streamable HTTP - **Auth:** OAuth 2.1 sign-in (preferred, nothing to configure), or an API token ## Install Give the client the endpoint URL and nothing else. It discovers the sign-in by itself. Find the client you are running in below. ### VS Code From a terminal, for your user profile. ```bash code --add-mcp '{"name":"skill-router","type":"http","url":"https://skills.sidekick.systems/mcp"}' ``` Or .vscode/mcp.json in the repository. Safe to commit. ```json { "servers": { "skill-router": { "type": "http", "url": "https://skills.sidekick.systems/mcp" } } } ``` ### Copilot CLI Run once. It is saved to ~/.copilot/mcp-config.json. ```bash copilot mcp add --transport http skill-router https://skills.sidekick.systems/mcp ``` ### Claude Code Run once, in the project you want the skills in. ```bash claude mcp add --transport http skill-router https://skills.sidekick.systems/mcp ``` Then run /mcp inside Claude Code and choose skill-router to sign in. ### OpenCode opencode.json at the root of the repository. Safe to commit. ```json { "mcp": { "skill-router": { "type": "remote", "url": "https://skills.sidekick.systems/mcp", "enabled": true } } } ``` ### Codex CLI Add it, then sign in. ```bash codex mcp add skill-router --url https://skills.sidekick.systems/mcp codex mcp login skill-router ``` ### Anything else Register a remote / Streamable HTTP MCP server at `https://skills.sidekick.systems/mcp`. A client that implements MCP authorization needs no further configuration. ## What happens next — tell the person The first connection opens a browser on `https://skills.sidekick.systems`. **A person has to finish it**: they sign in with the GitHub account that belongs to the organization, check the name of the client that is asking, and press **Approve**. You cannot do this step for them. If you ran the install command, say that a browser window needs their approval rather than waiting silently. The connection then appears under Settings → API tokens on `https://skills.sidekick.systems`, where it can be revoked. ## Then make the skills trigger: stubs, synced at session start Connecting the server is not enough on its own. An MCP tool is only called when you think to call it, whereas a native skill's description is in front of you on every turn. So a repository that uses the library keeps one **stub** `SKILL.md` per skill in `.claude/skills/` — which Claude Code, GitHub Copilot and OpenCode all read: the skill's name and description as the trigger, over a body that says to call `get_skill`. A stub holds none of the skill's content, so it never goes stale and every real use is still recorded. You keep them in step yourself, through the MCP server you are already signed in to. No script and no API token. **1. Sync now.** Call `sync_skill_stubs` on the `skill-router` server. Pass `have`: the `stubs` object from `.claude/skills/.skill-router.json` — leave it out the first time, when that file does not exist. The answer is only what changed, with instructions for writing it; follow them. Pass `project` or `tags` to narrow it, and `server` if this MCP server is registered under a name other than `skill-router`. **2. Make it happen at the start of every session.** This is where the two main agents differ, so set up the one in use — or both, in a repository people open with either. ### Claude Code `.claude/settings.json` — if it exists: Merge the `SessionStart` entry into the existing `hooks`; keep everything else. ```json { "hooks": { "SessionStart": [ { "matcher": "startup", "hooks": [ { "type": "command", "command": "echo 'Skill Router: before anything else in this session, call the sync_skill_stubs tool on the skill-router MCP server. Pass as have the stubs object from .claude/skills/.skill-router.json, or leave have out if that file does not exist. Follow the instructions in the answer, then carry on with what the user asked. If the skill-router MCP server is not connected, say so once and carry on.'" } ] } ] } } ``` - A `SessionStart` hook's plain output is added to the context, so the hook is a bare `echo`. That is deliberate: on Windows without Git Bash the command runs in PowerShell, and a single-quoted `echo` is the one spelling both shells agree on. - It is context, not a turn: the sync happens when the person sends their first message, not before. - Skills are reloaded live, so a stub written during a session is usable in that session. - Hooks in a committed `.claude/settings.json` run for everybody who opens the repository, without a trust prompt. Say so when you propose committing it. ### GitHub Copilot (VS Code, Copilot CLI, the cloud agent) `.github/hooks/skill-router.json` — if it exists: This file is Skill Router's own; overwrite it. ```json { "version": 1, "hooks": { "sessionStart": [ { "type": "command", "bash": "echo '{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"additionalContext\":\"Skill Router: before anything else in this session, call the sync_skill_stubs tool on the skill-router MCP server. Pass as have the stubs object from .claude/skills/.skill-router.json, or leave have out if that file does not exist. Follow the instructions in the answer, then carry on with what the user asked. If the skill-router MCP server is not connected, say so once and carry on.\"},\"additionalContext\":\"Skill Router: before anything else in this session, call the sync_skill_stubs tool on the skill-router MCP server. Pass as have the stubs object from .claude/skills/.skill-router.json, or leave have out if that file does not exist. Follow the instructions in the answer, then carry on with what the user asked. If the skill-router MCP server is not connected, say so once and carry on.\"}'", "powershell": "Write-Output '{\"hookSpecificOutput\":{\"hookEventName\":\"SessionStart\",\"additionalContext\":\"Skill Router: before anything else in this session, call the sync_skill_stubs tool on the skill-router MCP server. Pass as have the stubs object from .claude/skills/.skill-router.json, or leave have out if that file does not exist. Follow the instructions in the answer, then carry on with what the user asked. If the skill-router MCP server is not connected, say so once and carry on.\"},\"additionalContext\":\"Skill Router: before anything else in this session, call the sync_skill_stubs tool on the skill-router MCP server. Pass as have the stubs object from .claude/skills/.skill-router.json, or leave have out if that file does not exist. Follow the instructions in the answer, then carry on with what the user asked. If the skill-router MCP server is not connected, say so once and carry on.\"}'", "timeoutSec": 10 } ] } } ``` `.github/copilot-instructions.md` — if it exists: Append the section; keep everything else. Skip it if it is already there. ```markdown ## Skill Router Skill Router: before anything else in this session, call the sync_skill_stubs tool on the skill-router MCP server. Pass as have the stubs object from .claude/skills/.skill-router.json, or leave have out if that file does not exist. Follow the instructions in the answer, then carry on with what the user asked. If the skill-router MCP server is not connected, say so once and carry on. ``` - Copilot's hook has to print JSON — plain output is not added to the context — and takes a separate command per shell. - **Do not rely on the hook alone.** Agent hooks are a Preview feature in VS Code, and Copilot CLI has shipped versions that discard what a `sessionStart` hook prints. The instructions file is read by every Copilot surface in every session, so it is the part that always works; the hook is the part that works without the model having to notice. Where both fire the sync runs once — the second answer is `upToDate`. - VS Code also reads Claude Code's `.claude/settings.json` hooks, but does nothing with plain output, so the two files do not double up. - The cloud agent has no browser to sign in with. It reaches this MCP server only with an API token in its MCP configuration (see below); the hook and the stubs are the same. **3. Ask whether to commit.** `.claude/skills/` holds no secret and no skill content, so committing it — stubs, state file and the hook files above — gives the whole team the triggers from their first session. The alternative is ignoring the directory and letting each person's first session fill it. Either works; it is the person's call. A skill with no description gets a stub that will rarely trigger. The fix is to write the description in Skill Router, not to edit the stub — edits to a stub are overwritten. **Where there is no agent** — CI, a setup script — the same stubs come from a standalone script. It runs outside any MCP client, so it does need an API token, which a person creates at `https://skills.sidekick.systems/settings/tokens`: ```bash curl -fsSL https://skills.sidekick.systems/sync-skills.mjs -o sync-skills.mjs SKILL_ROUTER_URL=https://skills.sidekick.systems SKILL_ROUTER_TOKEN=sr_... node sync-skills.mjs --dry-run ``` ## If the client cannot sign in Scripts, CI, and clients without OAuth present an API token instead. A person creates one at `https://skills.sidekick.systems/settings/tokens` — it is shown once — and the client sends it as a header: ```bash claude mcp add --transport http skill-router https://skills.sidekick.systems/mcp \ --header "Authorization: Bearer $SKILL_ROUTER_TOKEN" ``` Never write the token into a file that gets committed. Read it from the environment (`SKILL_ROUTER_TOKEN`) or the client's own secret storage. ## Using it 1. `list_skills` — the catalogue, with slugs. 2. `search_skills` — when you know the problem and not the name. 3. `get_skill` — the whole document. Pass a `reason`: why you reached for it. 4. `report_skill_usage` — afterwards, whether it helped or fell short. 5. `propose_skill_update` — opens a review; a person approves it. Nothing you send changes a skill directly. 6. `sync_skill_stubs` — at the start of a session, as above. Records no usage. ## Discovery, for clients - Protected resource metadata: `https://skills.sidekick.systems/.well-known/oauth-protected-resource` - Authorization server metadata: `https://skills.sidekick.systems/.well-known/oauth-authorization-server` - These instructions as plain text: `https://skills.sidekick.systems/llms.txt` - The stub sync script: `https://skills.sidekick.systems/sync-skills.mjs`