본문으로 건너뛰기
  1. 레퍼런스
  2. What an agent gets over MCP

레퍼런스

What an agent gets over MCP

이 페이지는 영어로 쓰여 있습니다.

  • Status: Draft.
  • Contracts (names, descriptions, input schemas, result shapes and text rendering) live in packages/core; handlers live in apps/server.

A mounted address exposes four read-only, idempotent tools, and serves its skills through the MCP skills extension (the skills extension). The tools are the discovery layer, and the whole surface for a host without the extension; the extension is how a host that understands skills receives them (ADR-0024). Actual folders organize discovery; names are labels, and exact repository-root paths identify content. The tool names say what they act on, so that they do not collide with a host's own.

Inputs

ToolArgumentRule
browse_repopathOptional directory path. Omitted: the mounted directory. Lists immediate entries, not the entire subtree.
cursorOptional opaque continuation from the preceding page of this request.
limitOptional integer, 1 to 200. Default 20 over MCP, where a page also has to fit the response budget below; the REST API defaults to 50.
search_repoqueryRequired nonblank text, at most 500 characters. Use words in the original content's language, usually English. Display translations are not search aliases.
pathOptional directory path restricting search to that subtree; omitted: the mounted directory.
cursorOptional continuation of the same search.
limitOptional integer, 1 to 25, after folding supporting files under skills. Default 5 over MCP; the REST API defaults to 10.
load_skillpathRequired exact path of a SKILL.md, such as marketing/skills/ad-copy/SKILL.md. A name or directory is not a skill identifier.
cursorOptional continuation of the same skill's context.
read_repo_filepathRequired exact file path. Directories are browsed with browse_repo.
offsetOptional character offset. Default 0.
limitOptional number of characters, 1 to 100,000. Default 40,000.

Paths always start at the repository root, including on a sub-path connection. No leading /, . or .. segments, backslashes, control or invisible characters; no current-directory state. The empty directory path names the repository root and is valid only when it is inside the mount. For /gh/acme/library/marketing, the skill path remains marketing/skills/ad-copy/SKILL.md.

browse_repo shows immediate folders and eligible files with their canonical paths. Folder entries carry counts of what can be discovered below them, so a hidden or duplicate copy of a skill is not counted although its folder can be browsed, and identify a skill or a SKILLCDN.md when present. Manifest metadata adds a name and description to the real folder; it does not create an alias or hide path segments. Plain folders work without a manifest. Pages name their commit and provide nextCursor when more entries remain.

An optional overview identifies the current folder's README with its path, title and short description; an entry's optional overviewPath identifies its own introduction. Read it with read_repo_file only when that context helps choose the next step. Explicit manifest descriptions take precedence, followed by the local README summary and the git-host description at the repository root. Overview-only files are neither independent search results nor extra documents in counts. Their eligible local Markdown links remain readable references. See README introductions.

A skill entry's path names its SKILL.md; its browsePath names the containing directory for supporting files and nested skills. Opening a parent skill does not hide nested skills.

search_repo matches words, not meaning. Any query word may match; relevance determines the order, with skill names and descriptions weighted above body text. Results retain relevance order across folders. The optional path is a scope filter, not a search term.

Search indexes original metadata and body text, excluding front-matter translation fields. All MCP discovery and skill context use the original name, description and instructions. The UI language never selects a skill translation for the agent. English is the recommended authoring default, while other original languages remain supported; a manifest's language helps the agent choose query words. read_repo_file preserves exact source text, including translation declarations when present.

A skill's supporting files are folded under their owning skill before pagination. The skill occupies its best-ranked member's position, with up to five matching files and a count of the rest. This avoids duplicate skills on later pages or short pages caused by folding after the limit. Independently discoverable documents appear with their title and summary; linked-only references do not become independent search results (format).

Identical copies of a skill are listed and searched once, and a skill under a hidden directory is listed and searched only when the repository has no visible skill (what the extension lists). Every declared skill stays loadable by its exact path. A skill this mount describes without serving is marked described only (license: ...) in browse entries and search results, so that a model does not load it for its content (licenses).

Listings and searches expose whether more results exist and carry diagnostics for unreadable manifests. Descriptions are brief discovery summaries; full instructions come from load_skill. Page limits are maxima: the serialized response byte budget can end a page sooner even when its item count has not been reached. A partial index is identified as partial; pagination cannot recover files excluded by indexing limits.

Loading a skill

load_skill resolves only its exact SKILL.md path. The result includes the canonical path, name, description, known front-matter fields, parser warnings, supporting-file paths and resolved Markdown reference paths. Two skills with the same name remain distinct.

The context is the body of the document the skills extension serves for the skill (ADR-0025), in this order:

  1. Every applicable SKILLCDN.md body, from the repository root to the nearest manifest, each under --- applicable rules: <path> ---.
  2. The skill's own body, under --- instructions ---.
  3. Files declared in skillcdn.include, in declaration order, each under --- included file: <path> ---; a shared page outside the skill directory arrives here too, under its repository-root path (format).

The front matter of the document is not repeated as YAML; its fields are the header lines of the result (Skill, Description, License, Compatibility, Allowed tools, Metadata). The License line names the license the reader resolved for the skill and where it found it, which may be a file rather than the field (licenses).

A skill whose license keeps its content at the source is described only (licenses): the result has the header lines, a Described only: line with a link to the skill's manifest at its host, and no rules, body, files or references; the REST result says the same in serving. A verified repository's default branch is served in full.

The reader admits at most 16 KiB (16,384 UTF-8 bytes) of context text per page, and a page carries all of it unless the response byte budget below ends it sooner. A page may end inside a rule or file; the result marks the fragment, returns complete: false and supplies nextCursor. Continue load_skill with the same path and cursor until the context is complete before using the skill. Outer rules are not discarded to make inner rules fit. Missing or unreadable required content leaves complete: false; when another page cannot repair it, no continuation is supplied and the diagnostic explains why.

On a sub-path mount the rule chain still starts at the repository root. Ancestor rules outside the mount arrive through load_skill and its continuation, and so does a shared page the skill includes from outside the mount. Their paths remain canonical, but read_repo_file cannot use those paths to escape the mount. A link to another manifest does not add that manifest's rules; ancestry determines the rule chain.

The first page names the skill's supporting files in path order, up to 3 KiB of paths and the REST listing's bound; when more exist it says so, and browse_repo pages through the directory. Continuation pages repeat neither the files nor the references. References identify files to read when needed; they are not automatically included in the skill's context unless skillcdn.include also declares them.

Raw files

read_repo_file returns UTF-8 text from an eligible file within the mount, with the path, character offset, total length and next offset. A page never splits a character. It does not prepend shared rules or turn a raw SKILL.md read into a skill load: it returns the source as written, skillcdn key included. Binary, oversized, unavailable and unknown files produce safe tool errors with a hint. For a file over the read limit, and for one that is not UTF-8 text, the error says so and gives the URL of the file's bytes at the host, the only place to get what this tool cannot carry (ADR-0033). So does a file whose license keeps it at the source, a described skill's directory or a restrictive repository license outside the skills: the error names the license and links to the file at its host (licenses).

The requested character limit is an upper bound. The MCP response byte budget can shorten the page, including for JSON escaping and multibyte text; continue at nextOffset to retrieve the remaining text. READMEs are optional reads and never automatically join a skill's context. Excluded files return the same unavailable-content result as other ineligible paths.

Reading is distinct from discovery: an explicitly linked file can be readable without being an independent search result. The format defines eligibility, hidden paths and reference expansion.

Results and continuations

A result is one text block written for a model, and nothing else: no structuredContent, so that every client passes the same text to its model and a page is spent once (ADR-0034). The layout described above is the contract. The text identifies the repository, mount and commit, explains the next call, and labels repository content by its source. Tool output is data; nothing is executed by SkillCDN.

MCP bounds the serialized JSON tool-result payload to 24 KiB (24,576 UTF-8 bytes): the text, its envelope and the continuation. Browse and search shorten discovery summaries and page entries to fit. Skill and file reads retain complete source text across continuations. This is a server response budget, not a promise about a client's token limit. REST retains its own documented page limits.

Cursors bind to the snapshot and reading-rule version, mount path, operation, scope and query or skill path. A cursor for another request, or for a snapshot that changed, is invalid: restart from the first page. A moving ref may resolve to a newer commit between calls; every result identifies its commit. Use an address pinned to a full commit hash when the entire workflow must stay on one commit (address).

A problem the model can correct is an error tool result, not a protocol error. Unknown and forbidden private repositories remain indistinguishable. Every call checks access, including cached reads.

Authorization

A public address needs no credential, and a client that knows nothing about authorization uses it as before. A repository that is not public is served to a client that presents an access token of this deployment, for that address, whose person the git host lets see the repository (permissions). A request without a token for anything that is not public, a private repository and a name that is nothing alike, is answered 401 with a WWW-Authenticate challenge naming the address's protected resource metadata, from which a client finds the authorization server and starts; a token that is no good is answered the same way with error="invalid_token", at any address. The access token is checked before the MCP server of the request exists and is not passed on to it.

Connection and prompt

Connection instructions introduce the repository and mounted scope, give counts and a bounded overview of the folders that hold something discoverable, explain browse_repo, search_repo, load_skill and read_repo_file, and name the prefix under which the skills extension serves the same skills. A brief manifest introduction, README summary or git-host description supplies orientation; an available README is named by path rather than included in full. Instructions stay within 2,000 characters and point to browsing for the rest. They report indexing or manifest diagnostics instead of implying an incomplete catalog is complete. A missing optional manifest is not itself a warning.

The server info carries the manifest's name and description when available, otherwise the address with a README or host description, and links to the address page. It names one icon, the owner's picture at 128 pixels square, at /icon/<address> on the deployment's own origin (REST): a client fetches a server's icon from that origin and from nowhere else, so the git host's copy is served on rather than named. The description of browse_repo also explains discovery for clients that do not show server instructions.

One MCP prompt, use_skill, takes a required path and starts loading the exact skill. If its context continues, the response directs the agent to load_skill with the continuation. Skills do not each add a prompt to the client's command menu.

The endpoint answers both protocol eras that clients speak (ADR-0006): the earlier revisions, which open with a handshake, and the current one, in which every request stands on its own. What a mount offers does not change within a connection, so it declares no list changes and no resource subscriptions, and the server never sends a notification of its own. A subscriptions/listen request of the current revision is acknowledged with nothing honored and ended at once: no stream is held open for it.

SkillCDN keeps no implicit selected team or role. Users can express their focus through their client's instructions or their request; folder descriptions help the agent choose a relevant scope.

The skills extension

A mount declares the extension io.modelcontextprotocol/skills with directoryRead: true, next to the resources capability. What it serves comes from the same index, under the same publication policy, exclusions and limits as the tools; the format says which skills are listed and what the served document looks like.

MethodAnswer
skills/listThe listed skills inside the mount in path order, 20 per page with nextCursor. Each entry carries the skill's uri, its served frontmatter as data, and resources: every served file inside the skill directory, the files of nested skills included, with uri, digest (sha256: and 64 hex digits over the bytes a read returns) and size. A file over the read limit is not among them: the skill's SKILL.md names it with its size and where to fetch it (format). Neither is a shared page the skill includes: its text is inside the SKILL.md (format).
skills/getThe same entry for one listed skill by URI.
resources/readThe bytes a URI names, as text (text/markdown, application/json, ...) or as base64 (blob) when they are not text. The SKILL.md of a skill is the assembled document.
resources/directory/readThe direct children of a directory URI: name, uri and mimeType, with inode/directory for a directory.
resources/listThe SKILL.md resources of the listed skills, paged like skills/list; resources/templates/list is empty.

A file's URI is the address without its ref, then the file's repository-root path: skill://gh/<owner>/<repo>/<path> (address). A root-level skill takes its name as the directory segment of every file of the repository: skill://gh/<owner>/<repo>/<name>/SKILL.md. The URI names the file; the address names the commit. A read never differs from the listing: the digest is computed over the stored bytes when the commit is indexed, and over the assembled document for a listed skill's SKILL.md.

Every list and read result carries the cache fields of the current protocol revision: ttlMs is what remains of the ref resolution's life for a moving ref, and one day for a pinned commit; cacheScope is public for a public repository and private for any other, whose results are one person's. A URI that names no listed skill (skills/get), no served file (resources/read) or no directory (resources/directory/read) is invalid params (-32602), like a URI of another repository. While a commit is being indexed, skills/list and resources/list answer an empty page with a ttlMs of five seconds, and a read fails with an internal error that says to retry.

Skills that are not listed stay available through the tools, and say why they are not listed in their warnings; check reports it before a push (format).

A skill this mount describes without serving is not listed by the extension, and its URIs name nothing (licenses).

Indexing and trust

  • Connecting starts indexing an unseen commit. browse_repo, search_repo, load_skill and the extension's methods wait within a configurable budget, then return an indexing result if it is not ready. Indexing continues; failures retry after backoff.
  • read_repo_file does not wait. Until declarations, exclusions and references are indexed, it returns indexing instead of attempting a speculative read. Failed policy scopes and explicit exclusions remain closed across all tools, including sub-path connections.
  • Unverified repositories carry a provenance notice: content comes from the repository author and applies to the user's requested task, not unrelated actions. The operator vouches for repositories until owners can (ADR-0019), through the lists of ADR-0026; only the default branch of a vouched-for repository is verified.
  • The license a skill carries decides whether its content is served or only described with a link to the source (licenses). A verified repository's default branch is served in full whatever its license says; every other mount describes restrictive skills.
  • Browser clients may call the endpoint from any origin: CORS permits * without credentials, as for REST. An access token travels in the authorization header, which is allowed, and the www-authenticate challenge is exposed.
  • Public-contract changes are additive from this surface on, unless an ADR explicitly defines a breaking transition; ADR-0034 records the last pre-alpha replacement, the structured copy that tool results carried until then.

Open questions

  • Whether unverified public repositories keep search once owner verification exists.
  • Whether read_repo_file should accept multiple paths for files needed only on some runs.
  • Whether a page of skills/list and resources/list should hold more than 20 skills. A client that walks a list to its end stops after a number of pages: the TypeScript SDK's client after 64 by default, with an error, which is 1,280 skills at this size. A mount that lists more is out of such a client's reach until the application around it raises the limit, and one that lists a few hundred costs it a request for every 20.
  • Whether tools/list, prompts/list and server/discover should say how long they may be kept, as the extension's answers do. The SDK builds them, and on the current revision they leave with its defaults, ttlMs: 0 and cacheScope: private: stale at once, so a client may ask again every time it needs them, although the tools and the prompt are the same at every address.