diff --git a/.cursor-plugin/marketplace.json b/.cursor-plugin/marketplace.json
new file mode 100644
index 0000000..0918c28
--- /dev/null
+++ b/.cursor-plugin/marketplace.json
@@ -0,0 +1,18 @@
+{
+ "name": "agent-switchboard",
+ "owner": {
+ "name": "Agent Switchboard",
+ "email": "barnir@agentmail.to"
+ },
+ "metadata": {
+ "description": "The Agent Switchboard plugin for Cursor: search a curated directory of AI agents, MCP servers and agentic tools from the agent.",
+ "version": "1.0.0"
+ },
+ "plugins": [
+ {
+ "name": "agent-switchboard",
+ "source": "./plugins/agent-switchboard",
+ "description": "Search a curated directory of AI agents, MCP servers and agentic tools, compare them, find alternatives, and build one MCP config for several."
+ }
+ ]
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1dc1de1..137b2ac 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,11 @@ Every release of [Agent Switchboard](https://agentswitchboard.dev), newest first
Versions follow MAJOR.MINOR.PATCH: a minor version adds features, a patch fixes or adjusts. Versions before 2.2.0 were assigned afterwards, reconstructed from the git history. "Directory" lines summarize catalog changes since the previous release; the full log of every listing added, updated or removed is on [/changelog](https://agentswitchboard.dev/changelog), and batch by batch on [/drops](https://agentswitchboard.dev/drops). From 2.2.0 on, each minor release opens with its highlights, what you can do now with a link to try it, which [/whats-new](https://agentswitchboard.dev/whats-new) also shows.
+## [2.8.2] - 2026-11-03 - Cursor plugin
+
+### Added
+- A Cursor plugin for the Cursor Marketplace: [plugins/agent-switchboard](https://github.com/assafbar2/agentswitchboard.dev/tree/main/plugins/agent-switchboard) adds the Agent Switchboard MCP server to Cursor in one install, with no account or key. Until the marketplace lists it, add the server by URL as [/connect](https://agentswitchboard.dev/connect) shows. ([#322](https://github.com/assafbar2/agentswitchboard.dev/pull/322))
+
## [2.8.1] - 2026-11-02 - Code and data licenses
### Changed
diff --git a/DISTRIBUTION.md b/DISTRIBUTION.md
index c0baac3..ff6bb0a 100644
--- a/DISTRIBUTION.md
+++ b/DISTRIBUTION.md
@@ -25,7 +25,7 @@ or a placement-dependent order reaches either surface.
| Claude Connectors Directory | ◻ Ready to submit | — | Assaf submits at claude.ai/directory/manage (paid Claude plan). Custom connector by URL works today; /connect has a prefilled install link |
| ChatGPT plugin directory | ◻ Ready to submit | — | Assaf uploads a plugin ZIP at platform.openai.com (verified identity) and sets `OPENAI_APPS_CHALLENGE` in Vercel for domain verification. Custom MCP plugin by URL works today |
| GitHub MCP Registry (github.com/mcp, VS Code) | ◻ Not listed | — | Curated from the official registry by manual onboarding: request in github/github-mcp-server discussions or partnerships@github.com |
-| Cursor Marketplace | ◻ Not listed | — | Public repo with a Cursor plugin manifest, submitted at cursor.com/marketplace/publish (manual review) |
+| Cursor Marketplace | ◻ Ready to submit | [plugins/agent-switchboard](plugins/agent-switchboard) | Assaf applies at cursor.com/marketplace/publish (Cursor sign-in) with this repo's URL; Cursor reviews it by hand |
| Smithery | ◻ Not listed | — | Publish the hosted URL at smithery.ai/new (Smithery account) |
| Microsoft 365 Copilot connectors | ◻ Not listed | — | Partner Center, verified publisher; every tool needs a title and `readOnlyHint` (already set) |
@@ -50,5 +50,14 @@ curl -s -X POST http://localhost:3100/api/mcp \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"check","version":"1.0"}}}'
```
+**Cursor Marketplace**: the plugin lives in [plugins/agent-switchboard](plugins/agent-switchboard)
+(Cursor Plugin format: `.cursor-plugin/plugin.json`, `mcp.json`, `assets/logo.svg`, `README.md`),
+registered by [.cursor-plugin/marketplace.json](.cursor-plugin/marketplace.json) at the repo root.
+Cursor reviews every update before it ships, so bump `version` in the plugin's `plugin.json` when
+its files change. [tests/cursor-plugin.test.ts](tests/cursor-plugin.test.ts) checks it against
+Cursor's submission checklist and keeps its README's tool list, MCP URL and logo in step with the
+server. To try it in Cursor, copy the folder to `~/.cursor/plugins/local/agent-switchboard`,
+run Developer: Reload Window, and check Customize for the `agent-switchboard` MCP server.
+
**awesome-mcp-servers**: the listing line lives in their README (Search & Data Extraction
section) with a Glama score badge. Edit via PR only.
diff --git a/package-lock.json b/package-lock.json
index 4a2d222..7e30065 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "agentswitchboard.dev",
- "version": "2.8.1",
+ "version": "2.8.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "agentswitchboard.dev",
- "version": "2.8.1",
+ "version": "2.8.2",
"license": "MIT",
"dependencies": {
"@mcp-b/webmcp-polyfill": "^5.0.1",
diff --git a/package.json b/package.json
index 7a1439d..02f9f6f 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "agentswitchboard.dev",
- "version": "2.8.1",
+ "version": "2.8.2",
"private": true,
"scripts": {
"dev": "next dev",
diff --git a/plugins/agent-switchboard/.cursor-plugin/plugin.json b/plugins/agent-switchboard/.cursor-plugin/plugin.json
new file mode 100644
index 0000000..9357150
--- /dev/null
+++ b/plugins/agent-switchboard/.cursor-plugin/plugin.json
@@ -0,0 +1,15 @@
+{
+ "name": "agent-switchboard",
+ "displayName": "Agent Switchboard",
+ "version": "1.0.0",
+ "description": "Search a curated directory of AI agents, MCP servers and agentic tools, compare them, find alternatives, and build one MCP config for several.",
+ "author": {
+ "name": "Agent Switchboard",
+ "email": "barnir@agentmail.to"
+ },
+ "homepage": "https://agentswitchboard.dev",
+ "repository": "https://github.com/assafbar2/agentswitchboard.dev",
+ "license": "MIT",
+ "keywords": ["mcp", "mcp-servers", "ai-agents", "directory", "search", "developer-tools"],
+ "logo": "assets/logo.svg"
+}
diff --git a/plugins/agent-switchboard/README.md b/plugins/agent-switchboard/README.md
new file mode 100644
index 0000000..de9f60a
--- /dev/null
+++ b/plugins/agent-switchboard/README.md
@@ -0,0 +1,47 @@
+# Agent Switchboard for Cursor
+
+Search [Agent Switchboard](https://agentswitchboard.dev), a curated directory of AI agents, MCP
+servers and agentic tools, from Cursor's agent. Ask which tool fits a job, read a listing's setup
+steps, compare listings, find alternatives, and get one MCP config for several tools.
+
+The plugin adds one MCP server, `https://agentswitchboard.dev/api/mcp` (Streamable HTTP). It needs
+no account, API key or configuration. In approval prompts it appears as
+`plugin-agent-switchboard-agent-switchboard`.
+
+## Tools
+
+| Tool | What it does |
+| --- | --- |
+| `search_agents` | Find listings for a job: by query, task, category, access method (MCP, API, CLI, SDK and more), sign-in type, or official and verified status |
+| `get_agent` | One listing with its description, access methods, and MCP address or install command |
+| `list_categories` | The directory's categories, with how many listings each has |
+| `compare_agents` | Two or three listings side by side |
+| `alternatives_to` | Listings that could stand in for one, with what each has in common |
+| `connect_bundle` | One MCP client config for up to 10 listings, and how to connect the rest |
+| `submit_listing` | Suggests a missing product by filing a public GitHub issue for human review. It publishes nothing. It is marked destructive, so clients ask before calling it |
+
+Every tool except `submit_listing` is read-only.
+
+## Try it
+
+- "Find an MCP server that can query a Postgres database."
+- "How do I connect the Playwright MCP server, and is it official?"
+- "Compare GitHub Copilot, Cursor and Windsurf."
+- "What are good alternatives to Pinecone?"
+- "Give me one MCP config with Playwright MCP, GitHub MCP and Notion MCP."
+
+## Results and privacy
+
+Results are organic: they rank by relevance or A→Z, never by paid placement. The server receives
+only the arguments of each tool call, never your conversation or code. See the
+[privacy policy](https://agentswitchboard.dev/privacy).
+
+## License
+
+The plugin is MIT, like the rest of the repository's code. The catalog data its tools return is
+CC BY-NC 4.0; see [LICENSE-DATA](https://github.com/assafbar2/agentswitchboard.dev/blob/main/LICENSE-DATA).
+
+## Help
+
+Setup for other assistants and troubleshooting: [agentswitchboard.dev/connect](https://agentswitchboard.dev/connect#troubleshooting).
+Support: [agentswitchboard.dev/contact](https://agentswitchboard.dev/contact).
diff --git a/plugins/agent-switchboard/assets/logo.svg b/plugins/agent-switchboard/assets/logo.svg
new file mode 100644
index 0000000..8576aed
--- /dev/null
+++ b/plugins/agent-switchboard/assets/logo.svg
@@ -0,0 +1,16 @@
+
diff --git a/plugins/agent-switchboard/mcp.json b/plugins/agent-switchboard/mcp.json
new file mode 100644
index 0000000..c3295d9
--- /dev/null
+++ b/plugins/agent-switchboard/mcp.json
@@ -0,0 +1,7 @@
+{
+ "mcpServers": {
+ "agent-switchboard": {
+ "url": "https://agentswitchboard.dev/api/mcp"
+ }
+ }
+}
diff --git a/tests/cursor-plugin.test.ts b/tests/cursor-plugin.test.ts
new file mode 100644
index 0000000..31d28c4
--- /dev/null
+++ b/tests/cursor-plugin.test.ts
@@ -0,0 +1,81 @@
+/**
+ * The Cursor Marketplace plugin (.cursor-plugin/marketplace.json and
+ * plugins/agent-switchboard/) against Cursor's submission checklist
+ * (cursor.com/docs/reference/plugins), and in step with the live server:
+ * the MCP URL in server.json, the site icon, and every tool /api/mcp lists.
+ */
+import { describe, expect, it } from 'vitest';
+import * as fs from 'fs';
+import * as path from 'path';
+import { POST as mcpPost } from '@/app/api/[transport]/route';
+
+const ROOT = path.resolve(__dirname, '..');
+const readJson = (file: string) => JSON.parse(fs.readFileSync(path.join(ROOT, file), 'utf8'));
+
+const PLUGIN_NAME = /^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/;
+const marketplace = readJson('.cursor-plugin/marketplace.json');
+const entry = marketplace.plugins[0];
+const pluginDir = path.join(ROOT, entry.source);
+const manifest = readJson(path.join(entry.source, '.cursor-plugin/plugin.json'));
+const mcpConfig = readJson(path.join(entry.source, 'mcp.json'));
+const serverJson = readJson('server.json');
+
+function isSafeRelative(p: string) {
+ const normalized = path.posix.normalize(p);
+ return !path.isAbsolute(p) && normalized !== '..' && !normalized.startsWith('../');
+}
+
+async function listedTools(): Promise {
+ const res = await mcpPost(
+ new Request('http://localhost/api/mcp', {
+ method: 'POST',
+ headers: { 'content-type': 'application/json', accept: 'application/json, text/event-stream' },
+ body: JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }),
+ })
+ );
+ const text = await res.text();
+ const data = text.split(/\r?\n/).filter((l) => l.startsWith('data:')).pop();
+ const { result } = JSON.parse(data ? data.slice(5) : text);
+ return result.tools.map((t: { name: string }) => t.name);
+}
+
+describe('Cursor Marketplace plugin', () => {
+ it('has one marketplace entry that resolves to a plugin folder with a manifest', () => {
+ expect(marketplace.name).toMatch(PLUGIN_NAME);
+ expect(marketplace.owner.name).toBeTruthy();
+ expect(marketplace.plugins).toHaveLength(1);
+ expect(isSafeRelative(entry.source)).toBe(true);
+ expect(fs.existsSync(path.join(pluginDir, '.cursor-plugin/plugin.json'))).toBe(true);
+ expect(entry.name).toBe(manifest.name);
+ });
+
+ it('has a kebab-case name, a description, a semver version and a committed relative logo', () => {
+ expect(manifest.name).toMatch(PLUGIN_NAME);
+ expect(manifest.description.length).toBeGreaterThan(40);
+ expect(manifest.version).toMatch(/^\d+\.\d+\.\d+$/);
+ expect(isSafeRelative(manifest.logo)).toBe(true);
+ expect(fs.readFileSync(path.join(pluginDir, manifest.logo), 'utf8')).toBe(
+ fs.readFileSync(path.join(ROOT, 'app/icon.svg'), 'utf8')
+ );
+ });
+
+ it('adds only the public MCP server, with no variables or secrets', () => {
+ const servers = Object.values(mcpConfig.mcpServers) as Record[];
+ expect(servers).toEqual([{ url: serverJson.remotes[0].url }]);
+ expect(manifest.variables).toBeUndefined();
+ });
+
+ it('ships no rules, skills, agents, commands or hooks that discovery would pick up', () => {
+ for (const dir of ['rules', 'skills', 'agents', 'commands', 'hooks']) {
+ expect(fs.existsSync(path.join(pluginDir, dir)), dir).toBe(false);
+ }
+ expect(fs.existsSync(path.join(pluginDir, 'SKILL.md'))).toBe(false);
+ });
+
+ it('documents every tool the MCP server lists in its README', async () => {
+ const readme = fs.readFileSync(path.join(pluginDir, 'README.md'), 'utf8');
+ const tools = await listedTools();
+ expect(tools.length).toBeGreaterThan(0);
+ for (const tool of tools) expect(readme, tool).toContain(`\`${tool}\``);
+ });
+});