About Directories
Directories is an MCP server published by cursor in the Developer Tools category: plugins from the Cursor community.
The repository has 4.0K stars and 668 forks, with the last commit 3 days ago. Recent commit activity is the strongest signal that reported issues will get attention.
Install
git clone https://github.com/cursor/community-pluginsThis server has no ConduID identity, so agent calls to it are not receipted. Pin the version you install and review the source before granting it credentials.
Ask AI
Ask AI about Directories
Powered by Claude · Grounded in docs
Security checks
Static checks derived from the repository yesterday. Heuristics on the source, not an audit.
- ✓README presentThe repository ships documentation.
- !License declaredNo license file. Legally you have no right to use it in a product.
- !Tests presentNo tests found. Behaviour changes may go unnoticed between versions.
- ✓Dependencies pinnedA lockfile pins dependency versions.
- ✓No dynamic code executionSource scan found no eval, dynamic Function, or shell execution.
- !Scoped permissionsDoesn't declare a permission scope. Assume it can do anything its process can.
README
Cursor Directory
The directory of plugins from the Cursor community.
Project Structure
├── apps/
│ └── cursor/ # Next.js app
├── supabase/
│ └── migrations/ # Database migrations
└── package.json # Bun workspace config
All data lives in the database — there is no local data in the repo.
Getting Started
Prerequisites
Setup
- Clone the repo
git clone https://github.com/cursor/community-plugins.git
cd community-plugins
- Install dependencies
bun install
- Configure environment variables
cp apps/cursor/.env.example apps/cursor/.env
Fill in the required values:
| Variable | Required | Description |
|---|---|---|
NEXT_PUBLIC_SUPABASE_URL |
Yes | Supabase project URL |
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY |
Yes | Supabase Publishable key (sb_publishable_..., replaces the legacy anon key) |
SUPABASE_SECRET_KEY |
Yes | Supabase Secret key (sb_secret_..., replaces the legacy service role key) |
NEXT_PUBLIC_APP_URL |
No | Defaults to http://localhost:3000 |
- Run the database migrations
Apply the migrations in supabase/migrations/ to your Supabase project.
- Start the dev server
bun dev
Open http://localhost:3000.
Contributing
All content is submitted through the website — no pull requests needed for data.
Submit a Plugin
- Go to cursor.directory/plugins/new
- Sign in with GitHub or Google
- Paste a GitHub repo URL — we auto-detect components following the Open Plugins standard
- Click Submit
Auto-detected components:
| Component | Path |
|---|---|
| Rules | rules/*.mdc |
| MCP Servers | .mcp.json |
| Skills | skills/*/SKILL.md |
| Agents | agents/*.md |
| Hooks | hooks/hooks.json |
| LSP Servers | .lsp.json |
See the Open Plugins specification and plugin template for details.
Tech Stack
- Framework: Next.js (App Router, Turbopack)
- Runtime: Bun
- Database: Supabase (PostgreSQL)
- Job Queue: Supabase Queues (
pgmq) drained by a 1-min Vercel cron - Styling: Tailwind CSS
- UI: Radix UI + shadcn/ui
- Search: Fuse.js (client-side fuzzy search)
- URL State: nuqs
- Linting: Biome
Plugin security scan
Submitted plugins are auto-reviewed by a Cursor SDK agent (composer-2) running
in local mode against a fresh clone of the plugin's repo plus its inline
component content. The verdict (safe / suspicious / malicious) is written
back to plugins.scan_status and surfaces in the admin queue.
The scan is asynchronous and runs out of the request lifecycle:
- Enqueue — server actions and the recover-stuck-scans cron call
enqueuePluginScan(pluginId)which sends a message to theplugin_scanspgmq queue. - Kick — user-facing actions also fire
kickDrainAfterResponse()so the drain route is called vianext/serverafter()immediately after the response is flushed. Scans typically start within a few hundred ms. - Drain —
/api/queue/plugin-scans/drainreads one message (vt=900s,n=1), runsrunPluginScan(pluginId), archives the message on success, leaves it for VT-expiry on retryable error, or buries it afterMAX_ATTEMPTS=5deliveries. - Cron safety net — Vercel cron hits the same drain route every minute so any messages that missed their kick still get processed.
The drain route uses maxDuration = 800 (Vercel Pro+ Fluid Compute ceiling) and
relies on CURSOR_API_KEY + CRON_SECRET from the env file.
Managing plugins via MCP (admins)
Admins can moderate Community Plugins from Cursor through the MCP server at
/api/mcp. It exposes the same operations as /admin/plugins:
| Tool | Effect |
|---|---|
list_moderation_queue |
Flagged, scan issues, verification requests, or hidden plugins |
search_plugins, get_plugin |
Find a plugin and see its status, scan verdict, owner, and components |
list_moderation_events |
Moderation audit log (web and MCP) |
approve_plugin, approve_flagged_plugin |
Publish a hidden plugin; flagged/blocked plugins need the explicit approve_flagged_plugin |
unpublish_plugin, block_plugin |
Hide a plugin, or hide and permanently block it (with a reason) |
rescan_plugin |
Queue a new security scan (refused while one is in progress) |
set_plugin_verified, dismiss_verification_request |
Manage the verified badge |
Deleting plugins stays in the web admin. Write tools are rate-limited per admin
(mcp-moderation Vercel Firewall rule), and every change from the web admin or
MCP is recorded in the append-only plugin_moderation_events table.
Who is an admin
Admins are rows in the public.admins table, which also controls
/admin/plugins. Add or remove people in the Supabase dashboard (Table
Editor → admins) or with SQL. Changes apply on the next request; nothing
needs a redeploy. Fill in one of:
user_id: an existing account (auth.users.id).email: someone who hasn't signed in yet, or any of their accounts. It only matches a Google or GitHub sign-in whose provider verified that address; an email typed into an email/password signup never counts.
-- By email, works before they sign in with Google or GitHub
insert into public.admins (email, note) values ('jane@cursor.com', 'plugin moderation');
-- By account (check it's the right one first)
insert into public.admins (user_id, note)
select id, 'plugin moderation' from auth.users where email = 'jane@cursor.com';
-- Remove
delete from public.admins where email = 'jane@cursor.com';
How access works
- Supabase Auth is the OAuth 2.1 authorization server. Cursor signs in through a pre-registered public OAuth client (PKCE, no secret); dynamic client registration stays off.
- The consent page (
/oauth/consent) only lets admins approve, and only for the allowlisted OAuth client. The production client's ID is built intosrc/lib/mcp/auth.ts; a comma-separatedMCP_OAUTH_CLIENT_IDSreplaces it, for example for a local Supabase stack. /api/mcpverifies every bearer token (signature and expiry viagetClaims, plus a session check with the Auth server), requires the allowlistedclient_id, and requires the user to be an admin. Deleting someone'sadminsrow or signing them out cuts off MCP access immediately. Website session tokens are not accepted by the MCP server, and MCP tokens are not accepted as website sessions.
Setup
-
In the Supabase dashboard, enable Authentication → OAuth Server, set the authorization path to
/oauth/consent, and leave dynamic client registration off. The Site URL must be the app's origin. Use asymmetric JWT signing keys if clients request theopenidscope. Locally,supabase/config.tomlalready enables this. -
Apply the migrations (adds
plugin_moderation_eventsandadmins) and add the admins. When moving off the oldADMIN_USER_IDSenv var, copy its IDs in before deploying, then deleteADMIN_USER_IDSandNEXT_PUBLIC_ADMIN_USER_IDS:insert into public.admins (user_id, note) select btrim(id)::uuid, 'migrated from ADMIN_USER_IDS' from unnest(string_to_array('<ADMIN_USER_IDS value>', ',')) as id; -
Production's OAuth client is already registered and built in. For another Supabase project, register one and set
MCP_OAUTH_CLIENT_IDSto the printed client ID:cd apps/cursor && bun run mcp:create-oauth-clientIt registers Cursor's fixed callbacks (
https://www.cursor.com/agents/mcp/oauth/callbackandhttp://localhost:8787/callback); pass--redirect-uri <url>for others. -
Add the
mcp-moderationrate limit rule (60 requests / 1h, keyed by user) in Vercel Firewall. Until it exists, write tools aren't rate limited and the server logs an error. -
Admins add the server to their Cursor
mcp.json:{ "mcpServers": { "cursor-directory": { "url": "https://cursor.directory/api/mcp", "auth": { "CLIENT_ID": "12bb4179-e29a-4f99-a718-335ef4d0edb2", "scopes": ["email"] } } } }Cursor opens the consent page on first use. Keep the write tools out of Cursor's auto-run allowlist so each change is approved by a person.
Prefer this per-admin
mcp.jsonentry over a Cursor Team MCP server: team servers are also available to Cloud Agents, which run tools without asking for approval, and Cursor's docs don't say whether team servers accept a pre-registered OAuth client ID.
README fetched from the repository yesterday. The original is authoritative.