mirror of
https://github.com/sanity-io/agent-toolkit.git
synced 2026-09-14 18:39:20 +08:00
feat: support Agent Plugins (#81)
Signed-off-by: Jonah Snider <jonah@jonahsnider.com>
This commit is contained in:
@@ -23,5 +23,8 @@ jobs:
|
||||
- name: Validate skills
|
||||
run: npm run validate
|
||||
|
||||
- name: Validate Agent Plugin
|
||||
run: npm run validate:agent-plugin
|
||||
|
||||
- name: Validate Cursor plugin
|
||||
run: npm run validate:cursor-plugin
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ The repo uses npm (not pnpm).
|
||||
1. Fork the repo
|
||||
2. Install dependencies with `npm ci`
|
||||
3. Make your changes in `skills/<skill-name>/`
|
||||
4. Run `npm run validate:all` to check skill and plugin validity
|
||||
4. Run `npm run validate:all` to check Agent Skills, Agent Plugins, and client plugin validity
|
||||
5. Submit a PR
|
||||
|
||||
### Adding to an existing skill
|
||||
|
||||
@@ -13,6 +13,7 @@ Collection of resources to help AI agents build better with [Sanity](https://www
|
||||
|
||||
- **MCP server:** Direct access to your Sanity projects (content, datasets, releases, schemas) and agent rules.
|
||||
- **Agent skills:** Comprehensive best practices skills for Sanity development, content modeling, SEO/AEO, and experimentation. Includes 21 integration/topic guides and 26 focused best-practice rules.
|
||||
- **Agent Plugin:** `plugin.json`, `skills/`, and `mcp.json` components for any Agent Plugins-compatible client.
|
||||
- **Claude Code plugin:** MCP server, agent skills, and slash commands for Claude Code users. Available on the [official Anthropic plugin marketplace](https://claude.com/plugins/sanity).
|
||||
- **Cursor plugin:** MCP server, agent skills, and commands on the [Cursor Marketplace](https://cursor.com/marketplace/sanity).
|
||||
- **Codex plugin:** MCP server and agent skills for [OpenAI Codex](https://developers.openai.com/codex) users.
|
||||
@@ -25,7 +26,7 @@ Choose your path based on how you want agents to work with Sanity:
|
||||
|
||||
1. **MCP server** — Give your agent always up-to-date rules and full access to your Sanity projects. No local files to maintain. Works with Cursor, VS Code, Claude Code, Lovable, v0, Replit, OpenCode, and other MCP-compatible clients.
|
||||
2. **Agent skills** — Install best practices skills for Sanity, content modeling, SEO/AEO, and experimentation. Works with Cursor, Claude Code, and any [Agent Skills](https://agentskills.io)-compatible agent.
|
||||
3. **Plugin** — Install the Sanity plugin for Cursor or Claude Code. Bundles MCP server, agent skills, and commands.
|
||||
3. **Plugin** — Install the Sanity plugin for Cursor, Claude Code, or any Agent Plugins-compatible client. Bundles MCP server, agent skills, and commands.
|
||||
4. **Manual installation** — Copy the skill references locally for offline use. You'll need to update them yourself.
|
||||
|
||||
### Option 1: Install MCP server (recommended)
|
||||
@@ -186,7 +187,8 @@ See [Option 3](#option-3-install-plugin) for plugin installation.
|
||||
|
||||
### Option 3: Install plugin
|
||||
|
||||
Install the Sanity plugin to get MCP server, agent skills, and commands. Available on the [Claude Code marketplace](https://claude.com/plugins/sanity) and [Cursor Marketplace](https://cursor.com/marketplace/sanity).
|
||||
Install the Sanity plugin to get MCP server, agent skills, and commands.
|
||||
Available on the [Claude Code marketplace](https://claude.com/plugins/sanity), [Cursor Marketplace](https://cursor.com/marketplace/sanity), or from this repo as an [Agent Plugin](https://agent-plugins.org/).
|
||||
|
||||
#### Claude Code
|
||||
|
||||
@@ -332,6 +334,8 @@ Just say: "Get started with Sanity" to begin.
|
||||
sanity-io/agent-toolkit/
|
||||
├── AGENTS.md # Knowledge router & agent behavior
|
||||
├── README.md # This file
|
||||
├── plugin.json # Portable Agent Plugins v1 manifest
|
||||
├── mcp.json # Portable Agent Plugins v1 MCP configuration
|
||||
├── .agents/plugins/ # Codex marketplace
|
||||
│ └── marketplace.json # Codex marketplace metadata
|
||||
├── .claude-plugin/ # Claude Code plugin configuration (distributed via claude-plugins-official)
|
||||
@@ -342,7 +346,7 @@ sanity-io/agent-toolkit/
|
||||
├── .cursor-plugin/ # Cursor plugin configuration (distributed via cursor.com/marketplace)
|
||||
│ ├── marketplace.json # Cursor marketplace metadata
|
||||
│ └── plugin.json # Per-plugin manifest
|
||||
├── .mcp.json # MCP server configuration
|
||||
├── .mcp.json # Legacy client MCP compatibility configuration
|
||||
├── assets/ # Plugin branding
|
||||
│ └── logo.svg # Sanity logo for marketplace display
|
||||
├── commands/ # Agent commands
|
||||
@@ -351,6 +355,7 @@ sanity-io/agent-toolkit/
|
||||
│ ├── typegen.md # /typegen
|
||||
│ └── deploy-schema.md # /deploy-schema
|
||||
├── scripts/ # Validation and CI scripts
|
||||
│ ├── validate-agent-plugin.mjs # Validate manifests against the v1 JSON Schemas
|
||||
│ └── validate-cursor-plugin.mjs # Cursor plugin validator
|
||||
└── skills/ # Agent skills (agentskills.io format)
|
||||
├── sanity-best-practices/ # Comprehensive Sanity skill
|
||||
@@ -378,6 +383,7 @@ All skills use `references/` for detailed content loaded on demand. The `sanity-
|
||||
- [Visual Editing guide](https://www.sanity.io/docs/visual-editing)
|
||||
- [Sanity TypeGen](https://www.sanity.io/docs/sanity-typegen)
|
||||
- [MCP server docs](https://www.sanity.io/docs/ai/mcp-server)
|
||||
- [Agent Plugins specification](https://agent-plugins.org/specification)
|
||||
- [Blueprints Infrastructure as Code](https://www.sanity.io/docs/compute-and-ai/blueprints)
|
||||
|
||||
---
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
|
||||
"mcpServers": {
|
||||
"Sanity": {
|
||||
"type": "streamable-http",
|
||||
"url": "https://mcp.sanity.io"
|
||||
}
|
||||
}
|
||||
}
|
||||
Generated
+60
-1
@@ -9,7 +9,25 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"skills-ref": "^0.1.5"
|
||||
"ajv": "8.20.0",
|
||||
"skills-ref": "0.1.5"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
"version": "8.20.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
|
||||
"integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"fast-uri": "^3.0.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"require-from-string": "^2.0.2"
|
||||
},
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/epoberezkin"
|
||||
}
|
||||
},
|
||||
"node_modules/argparse": {
|
||||
@@ -29,6 +47,30 @@
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-uri": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz",
|
||||
"integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==",
|
||||
"dev": true,
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
|
||||
@@ -42,6 +84,23 @@
|
||||
"js-yaml": "bin/js-yaml.js"
|
||||
}
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/require-from-string": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
|
||||
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/skills-ref": {
|
||||
"version": "0.1.5",
|
||||
"resolved": "https://registry.npmjs.org/skills-ref/-/skills-ref-0.1.5.tgz",
|
||||
|
||||
+4
-1
@@ -11,16 +11,19 @@
|
||||
"validate:experimentation": "skills-ref validate ./skills/content-experimentation-best-practices",
|
||||
"validate:pt-serialization": "skills-ref validate ./skills/portable-text-serialization",
|
||||
"validate:pt-conversion": "skills-ref validate ./skills/portable-text-conversion",
|
||||
"validate:agent-plugin": "node scripts/validate-agent-plugin.mjs",
|
||||
"validate:cursor-plugin": "node scripts/validate-cursor-plugin.mjs",
|
||||
"validate:all": "npm run validate && npm run validate:cursor-plugin"
|
||||
"validate:all": "npm run validate && npm run validate:agent-plugin && npm run validate:cursor-plugin"
|
||||
},
|
||||
"devDependencies": {
|
||||
"ajv": "8.20.0",
|
||||
"skills-ref": "0.1.5"
|
||||
},
|
||||
"keywords": [
|
||||
"sanity",
|
||||
"ai",
|
||||
"agent",
|
||||
"agent-plugins",
|
||||
"skills",
|
||||
"claude",
|
||||
"cursor",
|
||||
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
||||
"name": "sanity",
|
||||
"version": "1.0.0",
|
||||
"description": "Sanity plugin with an MCP server and agent skills for structured content development.",
|
||||
"author": {
|
||||
"name": "Sanity",
|
||||
"email": "support@sanity.io",
|
||||
"url": "https://www.sanity.io"
|
||||
},
|
||||
"homepage": "https://github.com/sanity-io/agent-toolkit",
|
||||
"repository": "https://github.com/sanity-io/agent-toolkit",
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"sanity",
|
||||
"cms",
|
||||
"content-lake",
|
||||
"groq",
|
||||
"content",
|
||||
"structured-content",
|
||||
"visual-editing"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { readFile } from "node:fs/promises";
|
||||
import process from "node:process";
|
||||
import Ajv2020 from "ajv/dist/2020.js";
|
||||
|
||||
const documents = [
|
||||
{
|
||||
path: "plugin.json",
|
||||
schemaUrl:
|
||||
"https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
||||
},
|
||||
{
|
||||
path: "mcp.json",
|
||||
schemaUrl: "https://agent-plugins.org/schemas/1.0.0/mcp.schema.json",
|
||||
},
|
||||
];
|
||||
|
||||
const ajv = new Ajv2020({ allErrors: true });
|
||||
let valid = true;
|
||||
|
||||
for (const document of documents) {
|
||||
const [schemaResponse, data] = await Promise.all([
|
||||
fetch(document.schemaUrl),
|
||||
readFile(document.path, "utf8").then(JSON.parse),
|
||||
]);
|
||||
|
||||
if (!schemaResponse.ok) {
|
||||
throw new Error(
|
||||
`Unable to load ${document.schemaUrl}: ${schemaResponse.status} ${schemaResponse.statusText}`
|
||||
);
|
||||
}
|
||||
|
||||
const validate = ajv.compile(await schemaResponse.json());
|
||||
if (!validate(data)) {
|
||||
valid = false;
|
||||
console.error(`${document.path} is invalid:`);
|
||||
console.error(ajv.errorsText(validate.errors, { separator: "\n" }));
|
||||
}
|
||||
}
|
||||
|
||||
if (!valid) process.exit(1);
|
||||
|
||||
console.log("Agent Plugin manifests are valid.");
|
||||
Reference in New Issue
Block a user