Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx agentmods add agents/markpasternak/canvas-drop/mcpgit clone --depth 1 https://github.com/markpasternak/canvas-dropWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/agents/markpasternak/canvas-drop/mcp)<a href="https://agentmods.dev/agents/markpasternak/canvas-drop/mcp"><img src="https://agentmods.dev/badge/agents/markpasternak/canvas-drop/mcp.svg" alt="Measured on agentmods" height="20"></a>What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5 | $0.00000 | $0.04124 |
| Opus 5 | $0.00000 | $0.02062 |
| Sonnet 5 | $0.00000 | $0.00825 |
| Haiku 4.5 | $0.00000 | $0.00412 |
Grade A, and why
mcp scanned grade A with 1 finding against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 3d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Makes network callslowCapability
Not a fault in itself. Listed so you know the mod talks to something, and to what.
| `create_canvas` | Create a canvas; returns its id, URL, a one-time deploy key, and a `deploy` block of ready-to-run curl endpoints (so you never probe for the API host). Optional `orgId` homes it in an org you belong t How it starts
The opening of the file, as written. The whole thing — 185 lines — stays where its author put it; the contents beside it link to each section on GitHub.
MCP server
canvas-drop exposes a remote Model Context Protocol endpoint so an MCP-capable agent host (Claude, ChatGPT, …) can connect once and then create, deploy, and manage the canvases you own — with no API key to paste. It is the identity-scoped companion to the keyed Deploy API: the Deploy API acts on one canvas with its secret key; MCP acts across your whole account as you.
Connect
Add the instance's MCP endpoint to your client:
{base}/mcp
On first use the client runs an OAuth 2.1 sign-in: it discovers the authorization
server (RFC 8414/9728 .well-known metadata), registers itself automatically
(Dynamic Client Registration), and opens a browser to this instance's normal login
(the same org sign-in you use for the dashboard). No second account, no secret to copy.
canvas-drop is its own authorization server — it does not proxy your IdP. In oidc
mode an unauthenticated agent is bounced through the usual login; in proxy/dev
mode identity is already resolved. The client stores the resulting access token (1h
TTL) and refreshes it automatically (refresh tokens rotate on use).
Identity always comes from that server-side sign-in — never from anything the client asserts. The email-domain allowlist is enforced before any token is issued, and every tool call re-checks that your account is still active, so a block or de-allowlist kills a live token on the next request.
Tools
Owner-management tools are scoped to your account. A canvas you don't own reads as
not found — there is no cross-owner owner-surface access and no existence leak.
Identity-scoped discovery tools are explicit exceptions: list_shared_canvases
returns only non-owned canvases you can already open and whose owner made them
discoverable in Shared.
| Tool | What it does |
|---|---|
whoami |
The connected account (id, email, name). When an org boundary is configured, also orgs ([{id, name}] you're a member of), teams (the teams you belong to), and isGuest (true = signed in but in no org) — use an org id as create_canvas's orgId. |
list_canvases |
The canvases you own. Optional query filter — a forgiving text search over title, description, tags, and slug (case/accent/whitespace-insensitive; multiple words are AND-ed) — an optional tags filter (any-match — canvases carrying any of the given tags), plus sort (updated default, or created/title/popular), and limit (1–100, default 50). sort=popular ranks by trending views (last 30 days); every item carries recentViews (that 30-day count) plus lifetime viewCount and lastViewedAt. |
create_canvas |
Create a canvas; returns its id, URL, a one-time deploy key, and a deploy block of ready-to-run curl endpoints (so you never probe for the API host). Optional orgId homes it in an org you belong to (from whoami.orgs) so it can be shared org-wide; omit or null for a personal canvas. Only meaningful when an org boundary is configured. |
get_canvas |
Current state of a canvas you own (includes lifetime viewCount + lastViewedAt; full stats via get_canvas_usage). |
list_versions |
Version history of a canvas you own (number, source, status, createdAt, fileCount, totalBytes, current, downloadUrl). |
delete_version |
Permanently delete one non-current ready version. The current version and disabled canvases are protected; shared draft/version blobs are retained. |
deploy_canvas |
Publish static files directly to live in one call — pass either a base64-encoded ZIP (zipBase64) or a files array (text as UTF-8, binary as base64). |
begin_deploy |
Open a staged upload from a file manifest (path, sha256, size); returns an uploadId and the subset of hashes you still need to send. |
add_files |
Stage files into an open upload (text as UTF-8, binary as base64); call repeatedly to chunk a large set. |
finalize_deploy |
Publish a new version from a staged upload. Single-use. |
get_canvas_file |
Read back what's live: list the current version's files, or fetch one file's content. Use it to verify a deploy (the live URL is sign-in gated — see below). |
rollback_canvas |
Point a canvas back at an earlier version number (must be a ready version). |
unpublish_canvas |
Take a published canvas back to draft. |
set_capabilities |
Toggle a canvas's backend capabilities — backendEnabled is the master switch; kv/files/ai/realtime are individual features (effective only when backend is on). Omitted fields are unchanged. |
set_canvas_slug |
Change a canvas's URL slug (pass a custom one, or omit for a fresh random slug). The old URL stops working immediately. |
regenerate_deploy_key |
Mint a new cd_… deploy key and invalidate the old one; the new key is returned once. |
archive_canvas |
Archive a canvas (reversible) — takes its URL offline and revokes any retained legacy guest sessions for that canvas. |
unarchive_canvas |
Restore an archived canvas back to active. |
delete_canvas |
Soft-delete a canvas — it loses its URL and is purged after the retention window. Blocked if an admin has disabled the canvas. Not reversible from MCP. |
update_canvas |
Update settings/sharing (Settings + Share tabs): title, description, access rung (private/specific_people/team/whole_org/public_link), discoverability (link_only or listed for Team / Whole-org shares; affects listing only, never URL access), password (or null to clear), sharedExpiresAt, spaFallback, previewMode (auto/off — the cover toggle; upload a custom image with set_canvas_preview), gallery listing/metadata, tags (the canvas's unified tag set — owner-list filtering and public gallery display; max 20, 50 chars each), and retained legacy guest-session AI settings where present. Setting galleryListed: true on a Whole-org canvas also sets discoverability: "listed", making it discoverable in Shared and in that organization’s gallery in one call. To share with teams, set access: "team" and teamIds (≥1 team you belong to — see list_teams; personal teams can be granted to any canvas you own, while org teams must match the canvas org); add discoverability: "listed" when team members should find it in Shared. Switching off team clears the grants. Server enforces the preconditions (sharing/listing need a published canvas; public_link needs the instance switch on and the owner account not revoked; a password un-lists). |
set_canvas_preview |
Set or clear a canvas's custom cover image (the dashboard's preview upload). Pass image (base64 png/jpeg/webp) to pin it as the cover (previewMode becomes custom, so a publish never overwrites it); omit image to clear it back to auto. |
list_access |
List active named people plus pending sign-in grants for a canvas you own (each with an id for revoke_access; legacy guest rows can still appear during migration). |
search_people |
Search eligible people for the Add person picker, scoped to a canvas you own or a team you can see. This mirrors the dashboard autocomplete and does not expose the admin People directory. |
grant_access |
Add a person by email. Existing users are granted now (status: granted); admissible new emails become pending auth-delegated grants (status: pending). No app-owned credential is created. Takes effect on the specific_people rung. |
invite_to_canvas |
Compatibility alias for adding a person and sending the access email when email is enabled. Prefer grant_access for new agent flows; both use the same Add person service and statuses. A brand-new external email is refused for a non-admin (NOT_PERMITTED) unless the instance allows it; RATE_LIMITED past the cap. |
revoke_access |
Remove an active person, pending sign-in grant, or legacy guest row. Legacy guest sessions are revoked when present. |
clone_canvas |
Clone a canvas into a new one you own — any active canvas you own, or a gallery template someone shared. Starts as an unpublished draft with a fresh slug + key. |
get_canvas_usage |
Usage stats: views + 30-day sparkline, and (backend-on) KV/file/AI/realtime op counts, storage, AI tokens/cost. |
list_teams |
The teams you belong to, each with mine (you're a member) and canManage (you created it — so you can rename/delete it). |
create_team |
Create a team. Omit orgId for a personal team (friends & family — add people by email when policy allows it); pass an orgId from whoami.orgs to attach it to that org. You become its first member and manager. |
rename_team / delete_team |
Rename or delete a team you created. Deleting unshares every canvas shared with it (the canvases are untouched). |
add_team_member / remove_team_member |
Add someone to a team you belong to by email, or remove a member (pass your own user id to leave). Returns status: granted (existing user joined now) or pending (a brand-new person joins on first sign-in). For an org team they must be a same-org member; a brand-new external email on a personal team is refused for a non-admin unless the instance allows it. |
list_team_members |
The roster of a team you belong to: active members (userId, email, name) plus pending invite rows (id, email, invitedAt) for people who haven't signed in yet. |
cancel_team_invite |
Cancel a pending invite on a team you belong to — the self-serve mirror of add_team_member (take back a typo'd email without an admin). Pass the pending row's id from list_team_members. |
list_shared_canvases |
Non-owned canvases discoverable to you in Shared: direct Specific-people grants, listed Team shares, and listed Whole-org shares. Takes optional query, sort (updated/title/owner), limit, and offset. Display-only; open via the returned url. |
get_draft |
The editor draft of a canvas you own — file list + state (dirty = differs from live). Creates it from the live version on first open. |
read_draft_file |
Read one draft file's content (text UTF-8 / binary base64). |
write_draft_file |
Write/replace a draft file (create: true refuses to overwrite). |
delete_draft_file |
Delete a draft file. |
rename_draft_file |
Rename/move a draft file. |
publish_draft |
Publish the draft as a new live version (the editor's Publish). |
restore_draft |
Reset the draft to a published version's files (the editor's Restore). |
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 3d ago First seen · 185 lines · 0 tokens per session scan A c42000adaed5
mcp is an agent published in the GitHub repository markpasternak/canvas-drop (7 stars, last pushed 21d ago), licensed MIT. It costs nothing until one of its globs matches a file; then it loads 4,124 tokens. A static security scan graded it A with 1 finding (makes network calls). No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-31.
Other agents, from other repositories
domain
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
issue-tracker
Issues and PRDs for this repo live in GitHub Issues for AmanVarshney01/create-better-t-stack. Use the gh CLI for issue operations.
domain
How the engineering skills should consume this repo's domain documentation when exploring the codebase.
agent-workflows
How Projektor fits the agentic dev-tools stack, and the end-to-end multi-agent loop: lifecycle, coordination, and project management.
tool-catalog
Every MCP tool Projektor exposes, generated from source.
flow-metrics
Every metric getflowmetrics returns, what it measures, and how to read it.