Skip to content

MCP tools

The tools knotless-mcp offers over stdio, and a public knotless-serve offers at /mcp. They name a repository as handle/name. Reads answer from a local cache mirror, writes go through the same code as the CLI, and errors come back as tool errors for the agent to read. One a PDS refused for want of scope, as a login from before knotless asked for more is, adds that the user signs in again: reconnecting knotless in their assistant, or running knotless login for a knotless on their machine. One the login asked for, but its PDS did not grant, says so instead: for a write in a space, that the PDS granted the collections the space type’s lexicon listed when the user signed in, and that signing in again grants this one once knotless’s lexicon lists it.

On a server, each account’s login with its PDS can end while its assistant’s token still works: a PDS ends a session after a lifetime of its own. Once the PDS turns down refreshing it, the server forgets the session, answers the next call 401 and the next token refresh invalid_grant, so the assistant has its user sign in again. A refresh that fails any other way is logged, and the call goes on. Agents says how to connect a client. Pulls, issues, diffs and files are resources to read by URI too.

Over stdio, knotless-mcp asks its appview about versions once a day, as the CLI does (Command reference). With a newer release out, the first tool’s answer ends with a text saying so. Older than the appview asks for, every tool fails, saying why and to run knotless upgrade, unless KNOTLESS_IGNORE_MINIMUM is set. /mcp on a server runs that server’s own build and does neither.

Every command knotless <group> <action> has one tool, <group>_<action>, with - as _: knotless repo star is repo_star, knotless pull update-branch is pull_update_branch. A tool takes what its command takes. A parameter is the flag’s name with - as _ (--keep-branch is keep_branch, --undo is undo), and the positionals are named as the command’s usage names them (repo, uri, name). Where a command has an undo, the tool takes undo: true. A verb that works on a pull or an issue exists as both tools (pull_close, issue_close). Every tool is a command, and nothing is on the MCP alone.

The commands with no tool act on the machine they run on: login, logout, upgrade, repo mirror, workflow pin and release download. The command reference has each command’s flags and what it prints; this page has what a tool takes beyond that and what it answers. The tools are listed by group, as the commands are. Actions lines them up against the commands, the methods and the pages.

knotless-mcp --read-only offers only the tools that read, as status, repo_list, repo_refs, repo_tree, repo_read, repo_blame, repo_search, repo_log, repo_diff, pull_diff, pull_show, issue_show, pull_list, issue_list, run_list, workflow_list and release_read (READS in crates/knotless-mcp/src/lib.rs lists them all), and runs no other, whatever login it has: for an agent that may read but must change nothing, as the review agent is.

status

Command knotless status

What it does a knotless-serve’s health, from /_status, for server (the appview by default), with repo (handle/name) its mirror too

account_profile

Command knotless account profile

What it does how you show on knotless, over your Bluesky profile, and, with bot, whether the account is a bot, which the feed leaves out

account_email, account_email_add, account_email_remove

Command knotless account email [add | remove]

What it does account_email says how many addresses you claim, {claimed}; account_email_add claims an address as yours and account_email_remove takes it back, each answering {changed, claimed}, how many you claim now

account_follow

Command knotless account follow

What it does follows a handle on knotless, or with undo unfollows it, answering {following, uri}

account_follows, account_followers

Command knotless account follows, knotless account followers

What it does account_follows lists whom a handle follows, yours by default, as {follows: [{handle, uri, createdAt}]}; account_followers who follows it, from the appview, as {followers: [{did, handle}]}

account_search

Command knotless account search

What it does the accounts owning public repositories whose handle holds text, as the appview’s search finds them, at most limit (10 by default, at most 50), as {owners: [{owner: {did, handle}, repoCount}]}

account_delegate

Command knotless account delegate

What it does hands your writes to a gateway (the appview’s, by default) so collaborators can push, approved in the browser

account_delete_data

Command knotless account delete-data

What it does without confirm, what knotless data your account holds, as getAccountData answers it; with confirm, your handle, deletes it all, answering {deleted, loggedOut}

repo_list, repo_refs, repo_tree, repo_log

Command knotless repo list, refs, tree, log

What it does read a repository, an account’s repositories, a directory (path, rev) or the history (rev, path, limit, 20 by default)

repo_read

Command knotless repo read

What it does a file at rev, optionally only lines start to end (long files)

repo_search

Command knotless repo search

What it does the lines holding a fixed string, in any case; see the parameters below

repo_blame

Command knotless repo blame

What it does who last changed each line of path at rev (the default branch if not given), as git blame finds it in the cache mirror: runs of lines, each {sha, start, count, author: {name, email, date}, summary, previous}, start counted from 1, date in UTC, and previous, where the commit’s parent had the file, that parent and the file’s path there

repo_diff

Command knotless repo diff

What it does what head changed since base; answers No differences: … when head changes nothing since base

repo_storage

Command knotless repo storage

What it does what a repository takes up on its PDS: its packs, their objects and bytes, and the bytes in blobs

repo_compact

Command knotless repo compact

What it does as the owner, fold a repository’s older packs into one and drop old claims and deleted refs’ leftover records, answering {before, removed, claims, refs}

repo_commit

Command knotless repo commit

What it does change files on a branch, optionally against a base commit, and with batch, as the owner, through the gateway; see the parameters below

repo_create

Command knotless repo create

What it does takes links ([{url, title?}], its website first) and a default_branch (main if not given) and names the runners given (none, for an empty list), or else the appview’s default runner, and returns them as runners: a private one’s are members, invited, with a warning (null otherwise) if one could not be. It answers the members who may push to a new repository

repo_edit

Command knotless repo edit

What it does change a repository’s description (empty drops it), its links ([{url, title?}], which replace those it had; empty drops them), its topics (names, which replace those it had; empty drops them), and the branch its HEAD names, one of its branches once it has any, answering {description, links, topics, defaultBranch}

repo_rename

Command knotless repo rename

What it does rename; the old name redirects

repo_archive

Command knotless repo archive

What it does makes one you own read only, or with undo writable again, answering {archivedAt} (null once unarchived)

repo_delete

Command knotless repo delete

What it does delete a repository you own and everything in it, with what you wrote about it; confirm is its name again, or it refuses

repo_transfer, repo_accept

Command knotless repo transfer, knotless repo accept

What it does offer a public repository to to, or with undo withdraw the offer; take one offered to you

repo_fork

Command knotless repo fork

What it does copy a repository into your account, under name if given

repo_share

Command knotless repo share

What it does let handle read a private repository, or with write push too, which first delegates your writes to the gateway when you have not, approved in the browser as account_delegate is, then answers who may read and write it and, as a second text, Delegated your writes to the gateway <did> first.; with undo takes access away

repo_members

Command knotless repo members

What it does who may read and push

repo_star, repo_stars

Command knotless repo star, knotless repo stars

What it does repo_star stars a public repository, or with undo takes the star back, answering {starred, uri}; repo_stars lists the repositories a handle starred, yours by default, as {stars: [{repo, uri, createdAt}]}

Parameters beyond a flag’s name:

repo_commit

Parameter changes

each {path} with one of content, base64, edits or delete: true; edits is a list of {old, new} made in turn in the file as the branch holds it, each old there exactly once, the file keeping its mode. A miss fails edit <n> of <path>: old is not in the file, or says how many times it is there; a path with no regular file fails <path>: no file there to edit. On a branch that moved, edits are made in the file as it is there (long files)

repo_search

Parameter path, context

only files under path, a directory, file or glob; with context, runs of lines around the matches instead of lines, each {path, start, end, matches, text}, matches the line numbers that match and text the run’s lines

repo_read

Parameter start, end

only those lines of a text file, from 1, end by default its last, as {start, end, lines, text}, lines the file’s count

repo_blame

Parameter start, end

only the runs for those lines, end by default start

branch_create, branch_delete, branch_rename

Command knotless branch create, delete, rename

What it does make, remove or rename a branch; a rename takes the open pulls on it along

branch_protect

Command knotless branch protect

What it does holds collaborators to a branch’s rules, or with undo drops them. Takes merges, queue, reviews (how many approvals, 0 to 10), code_owners, dismiss_stale and gates (handles or DIDs whose review of a pull’s head it waits for, see gates); into such a branch pull_merge refuses a pull not reviewed as it asks, naming what is missing, unless the owner forces it (see required reviews)

branch_rules

Command knotless branch rules

What it does lists the rules, a rule that asks for code owners with warnings when CODEOWNERS on its branch gives you, the owner, a path alone (your own pull changing it never has a code owner’s approval, as an author’s never counts, and merges only by force); shows queue

tag_create, tag_delete

Command knotless tag create, knotless tag delete

What it does make or remove a tag, such as a release’s version, at a commit, branch or tag

pull_create, issue_create

Command knotless pull create, knotless issue create

What it does open one, following the repository’s template: they refuse one with no body when there is a template. pull_create takes base, head_repo, head_branch, title, body, images, draft and reviewers

pull_template, issue_template

Command knotless pull template, knotless issue template

What it does what a repository asks a pull’s or issue’s title and body to follow: read before pull_create or issue_create

pull_list, issue_list

Command knotless pull list, knotless issue list

What it does takes a query in GitHub’s search words (collaboration.md), and says of each pull draft, true or false

pull_show, issue_show

Command knotless pull show, knotless issue show

What it does a pull or issue and its comments; on a pull, what it brings in and whether it merges cleanly, and on an issue mentionedBy, the pulls whose title or body names it, oldest first, each {pull, closes}, closes true where it names it after a closing keyword

pull_diff

Command knotless pull diff

What it does the diff a pull would apply, numbered as comment_add’s lines take them

pull_edit, issue_edit

Command knotless pull edit, knotless issue edit

What it does change your pull’s or issue’s title and text; pull_edit also whether your pull is a draft (draft, ready) and whom it asks to review it (reviewers, no_reviewers)

pull_close, pull_reopen, issue_close, issue_reopen

Command knotless pull close and the rest

What it does change an item’s state: its author, the owner or a collaborator; refuses an item that is not there, a merged pull and a state it is in already

pull_label, issue_label

Command knotless pull label, knotless issue label

What it does put labels on a pull or issue as owner, collaborator or triager, or with undo take them off

pull_assign, issue_assign

Command knotless pull assign, knotless issue assign

What it does assign a pull or issue to accounts, or with undo take them off; as in collaboration.md, the owner and collaborators assign. Answers assignees by DID

pull_ask_review

Command knotless pull ask-review

What it does ask accounts to review a pull, or with undo stop asking: the owner and collaborators, and a pull’s author in the pull. Answers assignees and reviewers, by DID

pull_dismiss_review

Command knotless pull dismiss-review

What it does dismiss a reviewer’s standing review of a pull, saying why: a comment naming it, so it counts for nothing, for or against, until they review again. As in collaboration.md: the owner and collaborators may, on their own pulls too. Answers the comment’s uri

pull_react, issue_react, comment_react

Command knotless pull react, knotless issue react, knotless comment react

What it does reacts to a pull, issue or comment (uri) on repo (in its space, for a private one) with a content among GitHub’s eight, or with undo takes it back, answering {reacted, uri}

pull_retarget

Command knotless pull retarget

What it does point a pull at other branches

pull_revert

Command knotless pull revert

What it does undoes a merged pull (uri) in one commit on revert/<rkey> and opens a pull of it into the same branch, saying reason if given, answering {pull, branch, commit} (reverting a pull)

pull_update_branch

Command knotless pull update-branch

What it does merges an open pull’s (uri) base into its branch and pushes it, answering {branch, commit, added}, commit absent when the branch held its base already, and added the paths where both sides only added lines and the base’s come first (updating a pull’s branch)

pull_merge

Command knotless pull merge

What it does merge a pull, queue it or check it; see below

pull_create, issue_create, pull_edit, issue_edit, comment_add, comment_edit

Parameters images

Answer pictures to show after the body, each {base64, alt}, a PNG, JPEG, WebP or GIF: uploaded, made smaller when over 1 MB, and attached (collaboration.md); with an edit, only beside a body

pull_create

Parameters draft, reviewers

Answer open it as a draft, which neither merges nor queues until marked ready; ask these accounts, by handle or DID, to review it (drafts and requested reviewers)

pull_edit

Parameters draft, ready, reviewers, no_reviewers

Answer for your pull: draft makes it a draft, ready marks it ready; ask more accounts to review it, or stop asking some

pull_list, issue_list

Parameters query

Answer also is:draft, -is:draft, review-requested:<handle, did or @me>, assignee:<handle, did or @me> and no:assignee

pull_diff

Parameters repo, uri, paths

Answer the pull’s unified diff, or with paths only those files’ parts of it (for a merged pull, what its merge brought in, from the commits its state records, so it answers once its branch is gone), each line of a hunk led by its line in the old file and in the new (blank on the side it is not on) and |, as comment_add’s lines takes them: a + line is side: new at its new number, a - line side: old at its old number, an unchanged line side: new at its new number. File headers, @@ lines and \ No newline are not numbered. A diff longer than 60,000 bytes so numbered, asked for without paths, answers instead said and files, each file’s path (a renamed file’s new one), added, removed and lines, to ask for by paths a few at a time, since an MCP client cuts off an answer that long

pull_show, issue_show

Parameters repo, uri

Answer item.draft, true or false for a pull, and item.reviewers, those it asks to review it, {did, handle, pending}, pending while the pull is open and they have not reviewed it, and false once it is merged or closed; for a pull, item.reviews: each reviewer’s standing review, {by, handle, verdict, commit, uri, outdated, maintainer, uncounted}, outdated once the open pull has moved past commit, maintainer for the owner or a collaborator, and uncounted, when its branch asks for reviews, why an approval does not count; on each comment, its author’s handle and facets, the accounts it mentions; on a comment on lines, line ({path, side, line, startLine}, side new and startLine the same as line where its record leaves them out) and review, which a review’s own comment names too; on each comment of a thread on lines, and on no other, resolved; on a review its reviewer’s later one stands in place of, superseded: true; and on an answer, reply; reactions, on it and on each comment, as {"<content>": count} or null, as the appview counts them, or for a private repository as its space has them; for a pull, also compare, which for a merged pull is what its merge brought in (base where the branch was before it, head the merge), whether or not its branch is still there; for a merged pull a merged revert undid, item.revertedBy, that revert, and on a revert, item.reverts, the pull it undoes; for an open pull in the queue or ejected from it, standing: {said, place, batch}

pull_merge takes wait (seconds, at most 300), force and keep_branch, as the CLI’s pull merge takes --wait, --force and --keep-branch. Merged, it answers {sha, method, deleted, kept, closed}: the commit its branch is at, how (merge or squash), the head branch it deleted, or else why it kept it (asked to, in another repository such as a fork, the branch merged into or the default branch, or named by another open pull), and the issues it closed.

With queue: true, on a branch protected with queue, it puts the pull in the merge queue instead and answers {"queued": {base, position, of}} at once, with ejectedBefore, why, when it is queued again at the very head the queue last ejected; it then ignores wait, force and keep_branch. Its description tells an agent to queue a pull once it builds, with the target branch merged in; once ejected, to read why and the failed checks’ logs, fix it and queue again, and to queue the same head again only when the failure is not the pull’s; and to stop after a second ejection for the same reason. Into a branch protected with queue (branch_protect takes queue, and branch_rules shows it), pull_merge without force queues the pull instead, answering {"queued": {base, position, of}, "why": "<base> takes pulls only through the merge queue"}; see queue-only branches.

With auto: true, on a branch with no merge queue, it sets the pull to merge by itself once its checks pass, and answers {"autoMerge": "set", "commit": <head>}; with undo: true as well, it cancels that, answering {"autoMerge": "cancelled"}. pull_show then has autoMerge, where it stands in words. See merge when checks pass.

With check: true, it merges nothing and answers whether it would now, as knotless pull merge --check says: {state, reason, conflicts, checks, method, deletes, base, head, may: {merge, force, queue, base, head, rerun}, queueOnly, reviews, reviewsMissing, reviewsUncounted, codeOwnersWarnings}: reviews is passed, blocked, or none when the branch asks for none, and reviewsMissing, reviewsUncounted (the approvals that do not count, and why) and codeOwnersWarnings are [{text}]. may is what the caller’s part in the repository lets it do, not whether that would work now: state and reason say that, and a blocked pull’s merge is refused, the owner’s too, unless the owner forces it. When the caller may not merge the pull, reason says so too. Over MCP, a refusal for reviews names the comment_add tool with verdict: "approve", and pull_merge with force, where the CLI names its commands.

standing.said reads as Queued, 3rd of 5, Queued, 1st of 2, running its checks, Queued, 1st of 2, running its checks again on main as it is now, Queued, 1st of 2, but its test failed. The runner ejects it, or runs it again if that run was on an older main, Queued, 2nd of 2, ready for the next batch, In a batch of 4 being checked, Landing, or Ejected: <reason>, with the failed checks.

comment_add

Command knotless comment add

What it does comments on a pull or issue, or reviews a pull: a body, and a verdict (approve or changes) for someone else’s pull; a comment’s URI as uri answers it in its thread. Answers {uri, written}: the first it wrote and all of them, and for an approval from someone who may not write to the repository, note, that it does not count toward a protected branch’s reviews

comment_edit

Command knotless comment edit

What it does change your comment’s text

comment_delete

Command knotless comment delete

What it does take your comment or review back

comment_react

Command knotless comment react

What it does as pull_react, to a comment

comment_resolve

Command knotless comment resolve

What it does resolve the thread a comment on a pull’s lines starts, or with undo open it again: its author, the pull’s, the owner or a collaborator

comment_add takes lines, comments on lines of a pull’s diff at its head, each {path, line, start_line?, side?, body} (side old for lines it removes), each starting a thread: with a body or verdict, as that review’s, all sent at once, otherwise on their own; at most 100.

label_list, label_define, label_delete

Command knotless label list, define, delete

What it does a repository’s labels: what it defines, defining one as owner (name, color, description, exclusive), or taking one away

triager_list, triager_add, triager_remove

Command knotless triager list, add, remove

What it does the accounts whose labels count, naming one as owner (handle, scopes) or dropping it

triager_eval

Command knotless triager eval

What it does how an account’s labels agree with everyone else’s, per scope, as [{scope, labelled, compared, agreed}]

queue_list

Command knotless queue list

What it does each pull waiting, in order, with its place and the batch it is in while that is checked or landing, or the preflight workflows it waits for, then the open pulls ejected

queue_leave

Command knotless queue leave

What it does takes a pull out, {"left": <uri>}; the owner and collaborators may

run_list

Command knotless run list

What it does what the repository’s runners report of its workflows, waiting for runs to finish if asked; each log is its last 8000 bytes; images returns a check’s pictures, at most 12 at once

run_log

Command knotless run log

What it does the newest check that ref, pull or queue, workflow and commit find, giving workflow when they find several: while it runs, what it printed so far as the appview holds it, {text, cursor, steps, going, ended, check}, text its last 8000 bytes; once it finished, {text, check}, text the end of its log. check is as run_list gives it

run_rerun

Command knotless run rerun

What it does as owner, ask the runners to run a ref or a pull again, or one workflow of either, with env at a ref

run_cancel

Command knotless run cancel

What it does as owner, ask the runners to cancel a ref’s or a pull’s runs going or waiting, or one workflow’s, {"asked": <uri>}

workflow_list

Command knotless workflow list

What it does the workflows at a ref (the default branch), and what runs each there: {ref, workflows: [{name, push, pull, asked, schedule, error}]}, schedule the [{cron}] it runs on at the default branch

runner_list, runner_add, runner_remove

Command knotless runner list, add, remove

What it does the accounts whose checks a repository shows; as owner, name or drop one: a private repository’s is made a member and invited, again each time it is added

runner_minutes

Command knotless runner minutes

What it does the minutes each of a repository’s runners counts for its owner’s public repositories in 30 days, against its allowance, and when minutes free up

agent_list, agent_add, agent_remove

Command knotless agent list, add, remove

What it does the accounts whose pulls a repository’s runners check as they move, as code no one vouches for; as owner, name or drop one

secret_list, secret_set, secret_remove

Command knotless secret list, set, remove

What it does the secrets a repository’s owner, or an admin of the organization that owns it, gives its runners: secret_set sets a name with its value, refs to limit it to some refs’ pushes and runners to some of the repository’s runners; secret_remove takes one back. They answer each, one per runner, name, runner, refs, key, updatedAt, never a value. A value given here passes through the conversation: for one that should not, run knotless secret set <url> <name> with it on stdin

run_list

Parameter ref

only the runs of pushes to that ref, in full, and those asked for there; a pull’s are found by pull, a batch’s by queue

run_list

Parameter queue

only the runs of that branch’s merge-queue batches, by its short name (main)

run_list

Parameter commit

only the runs of that commit: its hex ID, or at least its first 4 digits

run_list

Parameter wait

seconds to wait, at most 300, for a check to show and none to be queued or running; finding none by then is an error naming what was asked for

run_log

Parameter since

the cursor an earlier answer gave: only what the run printed after it, all the appview holds without it or for one of another run of the check

run_log

Parameter wait

seconds to wait, at most 300, for the check to show, then while it runs for it to print more after since, asking the appview again 25 s at a time: it answers as soon as there is more, the run’s steps end, or the time is up

release_yank

Command knotless release yank

What it does withdraw a version of a package from a repository you own, or with undo take that back (yanking), answering {uri}, the release’s

release_publish, release_list, release_read

Command knotless release publish, list, read

What it does releases (packages.md): release_publish publishes a version of a package from a repository you own, its files each {name, content} or {name, base64}, with optional commit, check and notes, answering {uri}; release_list lists a repository’s, of one package if given, as [{package, version, latest, yanked, commit, check, notes, createdAt, files: [{name, size, sha256}]}]; release_read reads one file of a version (the latest by default), checked, as {version, content} or {version, base64}, refusing a file over 1 MB

mod_hide

Command knotless mod hide

What it does as owner, hide a pull, issue or comment, or with undo show it again

mod_block, mod_blocks

Command knotless mod block, knotless mod blocks

What it does mod_block leaves out what a handle writes about your repositories, or one, or with undo stops; mod_blocks lists the accounts an account blocks, yours by default, the latest first: each did, handle, repo (the one repository, by its at:// URI as when blocked, or null for all) and createdAt

mod_report

Command knotless mod report

What it does report to the appview

As the appview’s operator: an account its KNOTLESS_ADMIN_DIDS names.

admin_takedown, admin_status, admin_reports, admin_stats, admin_logs

Command knotless admin takedown, status, reports, stats, logs

What it does take a subject down or, with undo, put it back; whether it is taken down; the reports received; how the appview is used; the lines it logged

An organization’s members as you may see them, yours or an account’s (org): the organization and its members see invitations and hidden members, anyone else public members, as public: true shows them to anyone.

ToolCommandWhat it does
org_addknotless org addinvites an account (admin: true for an admin) or changes a member’s role, keeping how it shows and when they joined, yours or, with org, one you are an admin of
org_removeknotless org removetakes a member out or withdraws an invitation, yours or, with org, one you are an admin of
org_joinknotless org joinwith visibility (public or hidden) accepts an invitation or changes how it shows
org_leaveknotless org leaveleaves
org_membersknotless org membersthe roster
org_listknotless org listthe organizations an account is a public member of
org_deleteknotless org deleteends yours

They answer {org, name, organization, inside, gateway?, entries: [{did, handle?, role, invitedAt, expiresAt?, joinedAt?, standing}], changed}: changed null, or for org_add {org, who, role, was?, had?, first, private} (first when it made the account an organization, private when the invitation is in the organization’s space rather than its public records), for org_remove {org, who, was?, organization}, for org_join {org, role, visibility}, for org_leave {left, warning}, for org_delete {removed: [entries]}. An organization’s admin changes its repositories’ settings with repo_edit, repo_archive, repo_compact, branch_protect, label_define, label_delete, triager_add, triager_remove, agent_add, agent_remove, runner_add, runner_remove, repo_share and secret_set from their own login, through the appview; repo_rename and repo_transfer take the organization’s own.

notification_list

Command knotless notification list

What it does what others did that concerns you, from the appview (a mention reason for a pull, issue or comment that names you as @handle, invite for an organization’s invitation you have yet to answer, its about the role it offers, and checks-failed and ejected for checks failing at your pull’s latest run and the merge queue taking it out, from the runner, with checks those that failed, as {workflow, status, check}), the latest limit (50 by default, 1 to 100), as {notifications: [{reason, author, about, repo, uri, subject, verdict, mentioned, lineComments, checks, new, createdAt}], markedSeen}: repo the repository as handle/name, for pull_show; subject what it is about, the pull or issue a comment is on, else the pull or issue itself, or for a star the repository’s record (null for a follow or an invitation); verdict a review’s; mentioned true when it names you though it is heard of for another reason, as a review of your pull that names you is heard of once, as a comment; lineComments how many line comments a review was sent with; and new whether it was new before this listing; marks them all seen after, unless peek, and markedSeen says it did, so the next listing has them new: false. kind lists only mentions, reviews, comments, pulls-and-issues, checks or stars-and-follows, and marks none seen

notification_settings

Command knotless notification settings

What it does which notifications you hear of, kept by the appview: on and off, lists of reasons (star, follow, pull, issue, comment, mention, review-requested, invite, checks-failed, ejected, subscribed, watching), and followed_only or anyone, change them first; answers {reasons: [{reason, enabled}], followed_only}

notification_watch

Command knotless notification watch

What it does what you hear of a repository (repo, handle/name) at level all (the default), releases or ignore; participating forgets the choice, but is kept for your own repository, watched at all until you choose. Answers {subject, level, createdAt}

notification_subscribe, notification_mute, notification_unsubscribe

Command knotless notification subscribe, mute, unsubscribe

What it does what you hear of a pull or an issue (uri): every comment, nothing but a review asked of you, or as your part in it says again. Answer {subject, level, createdAt}

notification_subscriptions

Command knotless notification subscriptions

What it does every choice, the latest first, as {subscriptions}

theme_check

Command knotless theme check

What it does a palette checked, answering {readable, shortfalls: [{text, on, ratio}]}, each text that would not read at 4.5 to 1 on what it is drawn on

theme_publish

Command knotless theme publish

What it does publishes a palette with a name as a dev.knotless.theme, answering {uri}, and with use draws your pages in it; a palette that falls short is neither published nor used

theme_use

Command knotless theme use

What it does draws your pages in a theme (system, light, dark, latte, mocha, dracula, pckt, plyr, blacksky, a published one’s at:// URI, or palette with a palette of your own), answering {using}, the name of what they are drawn in

theme_delete

Command knotless theme delete

What it does deletes one of yours by URI, answering {deleted}

theme_list

Command knotless theme list

What it does lists themes, everyone’s or a handle’s, the latest first, or with find those whose name starts so, as {themes: [{uri, name, creator, palette, createdAt}]}

The same server offers resource templates (resources/templates/list), so a client that reads MCP resources opens a pull, an issue, a diff or a file by URI rather than by a tool call: omp as read mcp://knotless://…, Claude Code as an @ mention. A URI mirrors the thing’s page on knotless.dev under the knotless:// scheme, {owner} a handle or DID and {did} and {rkey} those of the pull’s or issue’s at:// URI, as its page has them. Each answers with what its tool answers, read as the account the tools act as, and --read-only serves them all:

TemplateAnswers asType
knotless://{owner}/{repo}/pullspull_list, with no queryapplication/json
knotless://{owner}/{repo}/issuesissue_list, with no queryapplication/json
knotless://{owner}/{repo}/pull/{did}/{rkey}pull_show of at://{did}/dev.knotless.pull/{rkey}application/json
knotless://{owner}/{repo}/pull/{did}/{rkey}/diffpull_diff, with no paths: the numbered diff, or, too long to give whole, its said and files as JSONtext/plain
knotless://{owner}/{repo}/issue/{did}/{rkey}issue_show of at://{did}/dev.knotless.issue/{rkey}application/json
knotless://{owner}/{repo}/file/{rev}/{+path}repo_read at rev: text as it is, a binary file as a base64 blob (application/octet-stream)text/plain

A part is percent-escaped as a template’s expansion escapes it: a branch topic/x is topic%2Fx in {rev}, a DID’s : may be %3A, and {+path} keeps its /. resources/list lists none: there are too many to list. A URI no template makes is a -32002 (resource not found) error naming the templates. A read that fails is an error with the message its tool’s would have, and one past the account’s share of a server’s calls (see Agents) says to wait. Older than the appview asks for, a read fails as a tool does.

An agent pays for what it sends and reads as tokens, so the tools let it change part of a long file without moving all of it: repo_search with path and context finds the lines and what is around them, and repo_commit with edits sends only what changes. repo_read with start and end reads a part when the search shows too little.

The test an_agent_changes_a_line_of_a_long_file (crates/knotless-mcp/tests/mcp.rs) benches one change both ways, and fails if editing ever costs more than a fiftieth of rewriting:

One line of a 138 KB fileSentReceivedAboutTime
Before: repo_read, then repo_commit with content143,115 B138,207 B70,330 tokens473 ms
Now: repo_search with context, then repo_commit with edits313 B634 B236 tokens351 ms

Tokens are bytes over four. The run behind these numbers is the test’s own, against the reference PDS on one machine; cargo test -p knotless-mcp --test mcp an_agent_changes_a_line_of_a_long_file -- --nocapture prints them again. The saving grows with the file: what an edit sends does not.