cp-toolkit 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +130 -0
- package/bin/cp-kit.js +72 -0
- package/package.json +46 -0
- package/src/commands/add.js +212 -0
- package/src/commands/doctor.js +149 -0
- package/src/commands/init.js +662 -0
- package/src/commands/list.js +128 -0
- package/src/index.js +13 -0
- package/templates/agents/backend-specialist.md +263 -0
- package/templates/agents/code-archaeologist.md +106 -0
- package/templates/agents/database-architect.md +226 -0
- package/templates/agents/debugger.md +225 -0
- package/templates/agents/devops-engineer.md +242 -0
- package/templates/agents/documentation-writer.md +104 -0
- package/templates/agents/explorer-agent.md +73 -0
- package/templates/agents/frontend-specialist.md +556 -0
- package/templates/agents/game-developer.md +162 -0
- package/templates/agents/mobile-developer.md +377 -0
- package/templates/agents/orchestrator.md +416 -0
- package/templates/agents/penetration-tester.md +188 -0
- package/templates/agents/performance-optimizer.md +187 -0
- package/templates/agents/product-manager.md +112 -0
- package/templates/agents/product-owner.md +95 -0
- package/templates/agents/project-planner.md +406 -0
- package/templates/agents/qa-automation-engineer.md +103 -0
- package/templates/agents/security-auditor.md +170 -0
- package/templates/agents/seo-specialist.md +111 -0
- package/templates/agents/test-engineer.md +158 -0
- package/templates/github/agents/backend-specialist.md +67 -0
- package/templates/github/agents/code-archaeologist.md +61 -0
- package/templates/github/agents/database-architect.md +73 -0
- package/templates/github/agents/debugger.md +71 -0
- package/templates/github/agents/devops-engineer.md +85 -0
- package/templates/github/agents/documentation-writer.md +107 -0
- package/templates/github/agents/explorer-agent.md +87 -0
- package/templates/github/agents/frontend-specialist.md +54 -0
- package/templates/github/agents/game-developer.md +94 -0
- package/templates/github/agents/mobile-developer.md +75 -0
- package/templates/github/agents/orchestrator.md +48 -0
- package/templates/github/agents/penetration-tester.md +87 -0
- package/templates/github/agents/performance-optimizer.md +70 -0
- package/templates/github/agents/product-manager.md +85 -0
- package/templates/github/agents/product-owner.md +77 -0
- package/templates/github/agents/project-planner.md +83 -0
- package/templates/github/agents/qa-automation-engineer.md +95 -0
- package/templates/github/agents/security-auditor.md +72 -0
- package/templates/github/agents/seo-specialist.md +78 -0
- package/templates/github/agents/test-engineer.md +79 -0
- package/templates/github/instructions/database.instructions.md +74 -0
- package/templates/github/instructions/python.instructions.md +76 -0
- package/templates/github/instructions/security.instructions.md +73 -0
- package/templates/github/instructions/typescript.instructions.md +50 -0
- package/templates/rules/GEMINI.md +273 -0
- package/templates/scripts/mcp-server.js +704 -0
- package/templates/skills/core/behavioral-modes/SKILL.md +242 -0
- package/templates/skills/core/brainstorming/SKILL.md +163 -0
- package/templates/skills/core/brainstorming/dynamic-questioning.md +350 -0
- package/templates/skills/core/clean-code/SKILL.md +201 -0
- package/templates/skills/core/intelligent-routing/SKILL.md +335 -0
- package/templates/skills/core/mcp-builder/SKILL.md +176 -0
- package/templates/skills/core/parallel-agents/SKILL.md +175 -0
- package/templates/skills/core/plan-writing/SKILL.md +152 -0
- package/templates/skills/optional/api-patterns/SKILL.md +81 -0
- package/templates/skills/optional/api-patterns/api-style.md +42 -0
- package/templates/skills/optional/api-patterns/auth.md +24 -0
- package/templates/skills/optional/api-patterns/documentation.md +26 -0
- package/templates/skills/optional/api-patterns/graphql.md +41 -0
- package/templates/skills/optional/api-patterns/rate-limiting.md +31 -0
- package/templates/skills/optional/api-patterns/response.md +37 -0
- package/templates/skills/optional/api-patterns/rest.md +40 -0
- package/templates/skills/optional/api-patterns/scripts/api_validator.py +211 -0
- package/templates/skills/optional/api-patterns/security-testing.md +122 -0
- package/templates/skills/optional/api-patterns/trpc.md +41 -0
- package/templates/skills/optional/api-patterns/versioning.md +22 -0
- package/templates/skills/optional/app-builder/SKILL.md +75 -0
- package/templates/skills/optional/app-builder/agent-coordination.md +71 -0
- package/templates/skills/optional/app-builder/feature-building.md +53 -0
- package/templates/skills/optional/app-builder/project-detection.md +34 -0
- package/templates/skills/optional/app-builder/scaffolding.md +118 -0
- package/templates/skills/optional/app-builder/tech-stack.md +40 -0
- package/templates/skills/optional/app-builder/templates/SKILL.md +39 -0
- package/templates/skills/optional/app-builder/templates/astro-static/TEMPLATE.md +76 -0
- package/templates/skills/optional/app-builder/templates/chrome-extension/TEMPLATE.md +92 -0
- package/templates/skills/optional/app-builder/templates/cli-tool/TEMPLATE.md +88 -0
- package/templates/skills/optional/app-builder/templates/electron-desktop/TEMPLATE.md +88 -0
- package/templates/skills/optional/app-builder/templates/express-api/TEMPLATE.md +83 -0
- package/templates/skills/optional/app-builder/templates/flutter-app/TEMPLATE.md +90 -0
- package/templates/skills/optional/app-builder/templates/monorepo-turborepo/TEMPLATE.md +90 -0
- package/templates/skills/optional/app-builder/templates/nextjs-fullstack/TEMPLATE.md +82 -0
- package/templates/skills/optional/app-builder/templates/nextjs-saas/TEMPLATE.md +100 -0
- package/templates/skills/optional/app-builder/templates/nextjs-static/TEMPLATE.md +106 -0
- package/templates/skills/optional/app-builder/templates/nuxt-app/TEMPLATE.md +101 -0
- package/templates/skills/optional/app-builder/templates/python-fastapi/TEMPLATE.md +83 -0
- package/templates/skills/optional/app-builder/templates/react-native-app/TEMPLATE.md +93 -0
- package/templates/skills/optional/architecture/SKILL.md +55 -0
- package/templates/skills/optional/architecture/context-discovery.md +43 -0
- package/templates/skills/optional/architecture/examples.md +94 -0
- package/templates/skills/optional/architecture/pattern-selection.md +68 -0
- package/templates/skills/optional/architecture/patterns-reference.md +50 -0
- package/templates/skills/optional/architecture/trade-off-analysis.md +77 -0
- package/templates/skills/optional/bash-linux/SKILL.md +199 -0
- package/templates/skills/optional/code-review-checklist/SKILL.md +109 -0
- package/templates/skills/optional/database-design/SKILL.md +52 -0
- package/templates/skills/optional/database-design/database-selection.md +43 -0
- package/templates/skills/optional/database-design/indexing.md +39 -0
- package/templates/skills/optional/database-design/migrations.md +48 -0
- package/templates/skills/optional/database-design/optimization.md +36 -0
- package/templates/skills/optional/database-design/orm-selection.md +30 -0
- package/templates/skills/optional/database-design/schema-design.md +56 -0
- package/templates/skills/optional/database-design/scripts/schema_validator.py +172 -0
- package/templates/skills/optional/deployment-procedures/SKILL.md +241 -0
- package/templates/skills/optional/documentation-templates/SKILL.md +194 -0
- package/templates/skills/optional/frontend-design/SKILL.md +418 -0
- package/templates/skills/optional/frontend-design/animation-guide.md +331 -0
- package/templates/skills/optional/frontend-design/color-system.md +311 -0
- package/templates/skills/optional/frontend-design/decision-trees.md +418 -0
- package/templates/skills/optional/frontend-design/motion-graphics.md +306 -0
- package/templates/skills/optional/frontend-design/scripts/accessibility_checker.py +183 -0
- package/templates/skills/optional/frontend-design/scripts/ux_audit.py +722 -0
- package/templates/skills/optional/frontend-design/typography-system.md +345 -0
- package/templates/skills/optional/frontend-design/ux-psychology.md +541 -0
- package/templates/skills/optional/frontend-design/visual-effects.md +383 -0
- package/templates/skills/optional/game-development/2d-games/SKILL.md +119 -0
- package/templates/skills/optional/game-development/3d-games/SKILL.md +135 -0
- package/templates/skills/optional/game-development/SKILL.md +167 -0
- package/templates/skills/optional/game-development/game-art/SKILL.md +185 -0
- package/templates/skills/optional/game-development/game-audio/SKILL.md +190 -0
- package/templates/skills/optional/game-development/game-design/SKILL.md +129 -0
- package/templates/skills/optional/game-development/mobile-games/SKILL.md +108 -0
- package/templates/skills/optional/game-development/multiplayer/SKILL.md +132 -0
- package/templates/skills/optional/game-development/pc-games/SKILL.md +144 -0
- package/templates/skills/optional/game-development/vr-ar/SKILL.md +123 -0
- package/templates/skills/optional/game-development/web-games/SKILL.md +150 -0
- package/templates/skills/optional/geo-fundamentals/SKILL.md +156 -0
- package/templates/skills/optional/geo-fundamentals/scripts/geo_checker.py +289 -0
- package/templates/skills/optional/i18n-localization/SKILL.md +154 -0
- package/templates/skills/optional/i18n-localization/scripts/i18n_checker.py +241 -0
- package/templates/skills/optional/lint-and-validate/SKILL.md +45 -0
- package/templates/skills/optional/lint-and-validate/scripts/lint_runner.py +172 -0
- package/templates/skills/optional/lint-and-validate/scripts/type_coverage.py +173 -0
- package/templates/skills/optional/mobile-design/SKILL.md +394 -0
- package/templates/skills/optional/mobile-design/decision-trees.md +516 -0
- package/templates/skills/optional/mobile-design/mobile-backend.md +491 -0
- package/templates/skills/optional/mobile-design/mobile-color-system.md +420 -0
- package/templates/skills/optional/mobile-design/mobile-debugging.md +122 -0
- package/templates/skills/optional/mobile-design/mobile-design-thinking.md +357 -0
- package/templates/skills/optional/mobile-design/mobile-navigation.md +458 -0
- package/templates/skills/optional/mobile-design/mobile-performance.md +767 -0
- package/templates/skills/optional/mobile-design/mobile-testing.md +356 -0
- package/templates/skills/optional/mobile-design/mobile-typography.md +433 -0
- package/templates/skills/optional/mobile-design/platform-android.md +666 -0
- package/templates/skills/optional/mobile-design/platform-ios.md +561 -0
- package/templates/skills/optional/mobile-design/scripts/mobile_audit.py +670 -0
- package/templates/skills/optional/mobile-design/touch-psychology.md +537 -0
- package/templates/skills/optional/nextjs-react-expert/1-async-eliminating-waterfalls.md +312 -0
- package/templates/skills/optional/nextjs-react-expert/2-bundle-bundle-size-optimization.md +240 -0
- package/templates/skills/optional/nextjs-react-expert/3-server-server-side-performance.md +490 -0
- package/templates/skills/optional/nextjs-react-expert/4-client-client-side-data-fetching.md +264 -0
- package/templates/skills/optional/nextjs-react-expert/5-rerender-re-render-optimization.md +581 -0
- package/templates/skills/optional/nextjs-react-expert/6-rendering-rendering-performance.md +432 -0
- package/templates/skills/optional/nextjs-react-expert/7-js-javascript-performance.md +684 -0
- package/templates/skills/optional/nextjs-react-expert/8-advanced-advanced-patterns.md +150 -0
- package/templates/skills/optional/nextjs-react-expert/SKILL.md +267 -0
- package/templates/skills/optional/nextjs-react-expert/scripts/convert_rules.py +222 -0
- package/templates/skills/optional/nextjs-react-expert/scripts/react_performance_checker.py +252 -0
- package/templates/skills/optional/nodejs-best-practices/SKILL.md +333 -0
- package/templates/skills/optional/performance-profiling/SKILL.md +143 -0
- package/templates/skills/optional/performance-profiling/scripts/lighthouse_audit.py +76 -0
- package/templates/skills/optional/powershell-windows/SKILL.md +167 -0
- package/templates/skills/optional/python-patterns/SKILL.md +441 -0
- package/templates/skills/optional/red-team-tactics/SKILL.md +199 -0
- package/templates/skills/optional/seo-fundamentals/SKILL.md +129 -0
- package/templates/skills/optional/seo-fundamentals/scripts/seo_checker.py +219 -0
- package/templates/skills/optional/server-management/SKILL.md +161 -0
- package/templates/skills/optional/systematic-debugging/SKILL.md +109 -0
- package/templates/skills/optional/tailwind-patterns/SKILL.md +269 -0
- package/templates/skills/optional/tdd-workflow/SKILL.md +149 -0
- package/templates/skills/optional/testing-patterns/SKILL.md +178 -0
- package/templates/skills/optional/testing-patterns/scripts/test_runner.py +219 -0
- package/templates/skills/optional/vulnerability-scanner/SKILL.md +276 -0
- package/templates/skills/optional/vulnerability-scanner/checklists.md +121 -0
- package/templates/skills/optional/vulnerability-scanner/scripts/security_scan.py +458 -0
- package/templates/skills/optional/web-design-guidelines/SKILL.md +57 -0
- package/templates/skills/optional/webapp-testing/SKILL.md +187 -0
- package/templates/skills/optional/webapp-testing/scripts/playwright_runner.py +173 -0
- package/templates/workflows/brainstorm.md +113 -0
- package/templates/workflows/create.md +59 -0
- package/templates/workflows/debug.md +103 -0
- package/templates/workflows/deploy.md +176 -0
- package/templates/workflows/enhance.md +63 -0
- package/templates/workflows/orchestrate.md +237 -0
- package/templates/workflows/plan.md +89 -0
- package/templates/workflows/preview.md +81 -0
- package/templates/workflows/status.md +86 -0
- package/templates/workflows/test.md +144 -0
- package/templates/workflows/ui-ux-pro-max.md +296 -0
|
@@ -0,0 +1,704 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Antigravity Agent Toolkit - MCP Server
|
|
5
|
+
*
|
|
6
|
+
* Model Context Protocol server that exposes the Antigravity toolkit
|
|
7
|
+
* capabilities to AI assistants like GitHub Copilot.
|
|
8
|
+
*
|
|
9
|
+
* Features:
|
|
10
|
+
* - List and load agents
|
|
11
|
+
* - List and load skills
|
|
12
|
+
* - Execute workflows (slash commands)
|
|
13
|
+
* - Access shared context
|
|
14
|
+
*
|
|
15
|
+
* @version 1.0.0
|
|
16
|
+
* @license MIT
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
20
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
21
|
+
import {
|
|
22
|
+
CallToolRequestSchema,
|
|
23
|
+
ListToolsRequestSchema,
|
|
24
|
+
ListResourcesRequestSchema,
|
|
25
|
+
ReadResourceRequestSchema,
|
|
26
|
+
ListPromptsRequestSchema,
|
|
27
|
+
GetPromptRequestSchema,
|
|
28
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
29
|
+
import * as fs from 'fs/promises';
|
|
30
|
+
import * as path from 'path';
|
|
31
|
+
|
|
32
|
+
const AGENT_ROOT = process.env.AGENT_ROOT || path.join(process.cwd(), '.agent');
|
|
33
|
+
|
|
34
|
+
// ============================================================================
|
|
35
|
+
// HELPERS
|
|
36
|
+
// ============================================================================
|
|
37
|
+
|
|
38
|
+
async function fileExists(filePath) {
|
|
39
|
+
try {
|
|
40
|
+
await fs.access(filePath);
|
|
41
|
+
return true;
|
|
42
|
+
} catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function readMarkdownFile(filePath) {
|
|
48
|
+
try {
|
|
49
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
50
|
+
return content;
|
|
51
|
+
} catch (error) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async function listDirectory(dirPath) {
|
|
57
|
+
try {
|
|
58
|
+
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
59
|
+
return entries;
|
|
60
|
+
} catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function parseFrontmatter(content) {
|
|
66
|
+
const frontmatterRegex = /^---\n([\s\S]*?)\n---/;
|
|
67
|
+
const match = content.match(frontmatterRegex);
|
|
68
|
+
|
|
69
|
+
if (!match) return { frontmatter: {}, body: content };
|
|
70
|
+
|
|
71
|
+
const frontmatterStr = match[1];
|
|
72
|
+
const body = content.slice(match[0].length).trim();
|
|
73
|
+
|
|
74
|
+
const frontmatter = {};
|
|
75
|
+
for (const line of frontmatterStr.split('\n')) {
|
|
76
|
+
const [key, ...valueParts] = line.split(':');
|
|
77
|
+
if (key && valueParts.length) {
|
|
78
|
+
frontmatter[key.trim()] = valueParts.join(':').trim();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return { frontmatter, body };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// ============================================================================
|
|
86
|
+
// AGENT TOOLKIT FUNCTIONS
|
|
87
|
+
// ============================================================================
|
|
88
|
+
|
|
89
|
+
async function listAgents() {
|
|
90
|
+
const agentsDir = path.join(AGENT_ROOT, 'agents');
|
|
91
|
+
const entries = await listDirectory(agentsDir);
|
|
92
|
+
|
|
93
|
+
const agents = [];
|
|
94
|
+
for (const entry of entries) {
|
|
95
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
96
|
+
const name = entry.name.replace('.md', '');
|
|
97
|
+
const content = await readMarkdownFile(path.join(agentsDir, entry.name));
|
|
98
|
+
const { frontmatter } = parseFrontmatter(content || '');
|
|
99
|
+
|
|
100
|
+
agents.push({
|
|
101
|
+
name,
|
|
102
|
+
description: frontmatter.description || `${name} agent`,
|
|
103
|
+
skills: frontmatter.skills || '',
|
|
104
|
+
tools: frontmatter.tools || '',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return agents;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async function loadAgent(agentName) {
|
|
113
|
+
const agentPath = path.join(AGENT_ROOT, 'agents', `${agentName}.md`);
|
|
114
|
+
const content = await readMarkdownFile(agentPath);
|
|
115
|
+
|
|
116
|
+
if (!content) {
|
|
117
|
+
return { error: `Agent '${agentName}' not found` };
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
121
|
+
|
|
122
|
+
// Load associated skills
|
|
123
|
+
const skills = [];
|
|
124
|
+
if (frontmatter.skills) {
|
|
125
|
+
const skillNames = frontmatter.skills.split(',').map(s => s.trim());
|
|
126
|
+
for (const skillName of skillNames) {
|
|
127
|
+
const skillContent = await loadSkill(skillName);
|
|
128
|
+
if (!skillContent.error) {
|
|
129
|
+
skills.push(skillContent);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
name: agentName,
|
|
136
|
+
frontmatter,
|
|
137
|
+
instructions: body,
|
|
138
|
+
skills,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function listSkills() {
|
|
143
|
+
const skillsDir = path.join(AGENT_ROOT, 'skills');
|
|
144
|
+
const skills = [];
|
|
145
|
+
|
|
146
|
+
// Scan core skills
|
|
147
|
+
const coreDir = path.join(skillsDir, 'core');
|
|
148
|
+
const coreEntries = await listDirectory(coreDir);
|
|
149
|
+
for (const entry of coreEntries) {
|
|
150
|
+
if (entry.isDirectory()) {
|
|
151
|
+
const skillPath = path.join(coreDir, entry.name, 'SKILL.md');
|
|
152
|
+
const content = await readMarkdownFile(skillPath);
|
|
153
|
+
|
|
154
|
+
if (content) {
|
|
155
|
+
const { frontmatter } = parseFrontmatter(content);
|
|
156
|
+
skills.push({
|
|
157
|
+
name: entry.name,
|
|
158
|
+
category: 'core',
|
|
159
|
+
description: frontmatter.description || `${entry.name} skill`,
|
|
160
|
+
version: frontmatter.version || '1.0.0',
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Scan optional skills
|
|
167
|
+
const optionalDir = path.join(skillsDir, 'optional');
|
|
168
|
+
const optionalEntries = await listDirectory(optionalDir);
|
|
169
|
+
for (const entry of optionalEntries) {
|
|
170
|
+
if (entry.isDirectory()) {
|
|
171
|
+
const skillPath = path.join(optionalDir, entry.name, 'SKILL.md');
|
|
172
|
+
const content = await readMarkdownFile(skillPath);
|
|
173
|
+
|
|
174
|
+
if (content) {
|
|
175
|
+
const { frontmatter } = parseFrontmatter(content);
|
|
176
|
+
skills.push({
|
|
177
|
+
name: entry.name,
|
|
178
|
+
category: 'optional',
|
|
179
|
+
description: frontmatter.description || `${entry.name} skill`,
|
|
180
|
+
version: frontmatter.version || '1.0.0',
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return skills;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
async function loadSkill(skillName) {
|
|
190
|
+
const skillsDir = path.join(AGENT_ROOT, 'skills');
|
|
191
|
+
|
|
192
|
+
// Try core first, then optional
|
|
193
|
+
let skillPath = path.join(skillsDir, 'core', skillName, 'SKILL.md');
|
|
194
|
+
let category = 'core';
|
|
195
|
+
|
|
196
|
+
if (!await fileExists(skillPath)) {
|
|
197
|
+
skillPath = path.join(skillsDir, 'optional', skillName, 'SKILL.md');
|
|
198
|
+
category = 'optional';
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const content = await readMarkdownFile(skillPath);
|
|
202
|
+
|
|
203
|
+
if (!content) {
|
|
204
|
+
return { error: `Skill '${skillName}' not found in core/ or optional/` };
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
208
|
+
const skillDir = path.dirname(skillPath);
|
|
209
|
+
|
|
210
|
+
// Check for references
|
|
211
|
+
const referencesDir = path.join(skillDir, 'references');
|
|
212
|
+
const references = [];
|
|
213
|
+
if (await fileExists(referencesDir)) {
|
|
214
|
+
const refEntries = await listDirectory(referencesDir);
|
|
215
|
+
for (const ref of refEntries) {
|
|
216
|
+
if (ref.isFile()) {
|
|
217
|
+
references.push(ref.name);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check for scripts
|
|
223
|
+
const scriptsDir = path.join(skillDir, 'scripts');
|
|
224
|
+
const scripts = [];
|
|
225
|
+
if (await fileExists(scriptsDir)) {
|
|
226
|
+
const scriptEntries = await listDirectory(scriptsDir);
|
|
227
|
+
for (const script of scriptEntries) {
|
|
228
|
+
if (script.isFile()) {
|
|
229
|
+
scripts.push(script.name);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
return {
|
|
235
|
+
name: skillName,
|
|
236
|
+
category,
|
|
237
|
+
frontmatter,
|
|
238
|
+
instructions: body,
|
|
239
|
+
references,
|
|
240
|
+
scripts,
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async function listWorkflows() {
|
|
245
|
+
const workflowsDir = path.join(AGENT_ROOT, 'workflows');
|
|
246
|
+
const entries = await listDirectory(workflowsDir);
|
|
247
|
+
|
|
248
|
+
const workflows = [];
|
|
249
|
+
for (const entry of entries) {
|
|
250
|
+
if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
251
|
+
const name = entry.name.replace('.md', '');
|
|
252
|
+
const content = await readMarkdownFile(path.join(workflowsDir, entry.name));
|
|
253
|
+
const { frontmatter } = parseFrontmatter(content || '');
|
|
254
|
+
|
|
255
|
+
workflows.push({
|
|
256
|
+
command: `/${name}`,
|
|
257
|
+
name,
|
|
258
|
+
description: frontmatter.description || `${name} workflow`,
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
return workflows;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
async function loadWorkflow(workflowName) {
|
|
267
|
+
const cleanName = workflowName.replace(/^\//, '');
|
|
268
|
+
const workflowPath = path.join(AGENT_ROOT, 'workflows', `${cleanName}.md`);
|
|
269
|
+
const content = await readMarkdownFile(workflowPath);
|
|
270
|
+
|
|
271
|
+
if (!content) {
|
|
272
|
+
return { error: `Workflow '${workflowName}' not found` };
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
276
|
+
|
|
277
|
+
return {
|
|
278
|
+
command: `/${cleanName}`,
|
|
279
|
+
name: cleanName,
|
|
280
|
+
frontmatter,
|
|
281
|
+
instructions: body,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
async function loadRules() {
|
|
286
|
+
const rulesPath = path.join(AGENT_ROOT, 'rules', 'GEMINI.md');
|
|
287
|
+
const content = await readMarkdownFile(rulesPath);
|
|
288
|
+
|
|
289
|
+
if (!content) {
|
|
290
|
+
return { error: 'Base rules not found' };
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
294
|
+
|
|
295
|
+
return {
|
|
296
|
+
name: 'GEMINI',
|
|
297
|
+
trigger: frontmatter.trigger || 'always_on',
|
|
298
|
+
instructions: body,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function routeToAgent(request) {
|
|
303
|
+
// Keywords to agent mapping
|
|
304
|
+
const routingMatrix = {
|
|
305
|
+
// Frontend
|
|
306
|
+
'react|next|component|ui|css|tailwind|frontend|layout|style': 'frontend-specialist',
|
|
307
|
+
// Backend
|
|
308
|
+
'api|endpoint|route|express|node|backend|server': 'backend-specialist',
|
|
309
|
+
// Database
|
|
310
|
+
'database|schema|migration|prisma|sql|query|table': 'database-architect',
|
|
311
|
+
// Security
|
|
312
|
+
'security|auth|login|password|vulnerability|owasp': 'security-auditor',
|
|
313
|
+
// Testing
|
|
314
|
+
'test|coverage|unit|e2e|jest|playwright': 'test-engineer',
|
|
315
|
+
// Debug
|
|
316
|
+
'error|bug|fix|broken|not working|debug': 'debugger',
|
|
317
|
+
// DevOps
|
|
318
|
+
'deploy|docker|ci|cd|kubernetes|pipeline': 'devops-engineer',
|
|
319
|
+
// Mobile
|
|
320
|
+
'mobile|ios|android|react native|flutter|app': 'mobile-developer',
|
|
321
|
+
// Performance
|
|
322
|
+
'slow|optimize|performance|speed|lighthouse': 'performance-optimizer',
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
const lowerRequest = request.toLowerCase();
|
|
326
|
+
|
|
327
|
+
for (const [keywords, agent] of Object.entries(routingMatrix)) {
|
|
328
|
+
const regex = new RegExp(keywords, 'i');
|
|
329
|
+
if (regex.test(lowerRequest)) {
|
|
330
|
+
return agent;
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Default to orchestrator for complex/unclear requests
|
|
335
|
+
return 'orchestrator';
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// ============================================================================
|
|
339
|
+
// MCP SERVER SETUP
|
|
340
|
+
// ============================================================================
|
|
341
|
+
|
|
342
|
+
const server = new Server(
|
|
343
|
+
{
|
|
344
|
+
name: 'antigravity-agent-toolkit',
|
|
345
|
+
version: '1.0.0',
|
|
346
|
+
},
|
|
347
|
+
{
|
|
348
|
+
capabilities: {
|
|
349
|
+
tools: {},
|
|
350
|
+
resources: {},
|
|
351
|
+
prompts: {},
|
|
352
|
+
},
|
|
353
|
+
}
|
|
354
|
+
);
|
|
355
|
+
|
|
356
|
+
// ============================================================================
|
|
357
|
+
// TOOLS
|
|
358
|
+
// ============================================================================
|
|
359
|
+
|
|
360
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
361
|
+
return {
|
|
362
|
+
tools: [
|
|
363
|
+
{
|
|
364
|
+
name: 'list_agents',
|
|
365
|
+
description: 'List all available specialist agents in the Antigravity toolkit',
|
|
366
|
+
inputSchema: {
|
|
367
|
+
type: 'object',
|
|
368
|
+
properties: {},
|
|
369
|
+
required: [],
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
{
|
|
373
|
+
name: 'load_agent',
|
|
374
|
+
description: 'Load a specific agent with its instructions and skills',
|
|
375
|
+
inputSchema: {
|
|
376
|
+
type: 'object',
|
|
377
|
+
properties: {
|
|
378
|
+
name: {
|
|
379
|
+
type: 'string',
|
|
380
|
+
description: 'Agent name (e.g., frontend-specialist, backend-specialist)',
|
|
381
|
+
},
|
|
382
|
+
},
|
|
383
|
+
required: ['name'],
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
name: 'list_skills',
|
|
388
|
+
description: 'List all available skills in the Antigravity toolkit',
|
|
389
|
+
inputSchema: {
|
|
390
|
+
type: 'object',
|
|
391
|
+
properties: {},
|
|
392
|
+
required: [],
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
name: 'load_skill',
|
|
397
|
+
description: 'Load a specific skill with its instructions',
|
|
398
|
+
inputSchema: {
|
|
399
|
+
type: 'object',
|
|
400
|
+
properties: {
|
|
401
|
+
name: {
|
|
402
|
+
type: 'string',
|
|
403
|
+
description: 'Skill name (e.g., clean-code, testing-patterns)',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
required: ['name'],
|
|
407
|
+
},
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
name: 'list_workflows',
|
|
411
|
+
description: 'List all available slash command workflows',
|
|
412
|
+
inputSchema: {
|
|
413
|
+
type: 'object',
|
|
414
|
+
properties: {},
|
|
415
|
+
required: [],
|
|
416
|
+
},
|
|
417
|
+
},
|
|
418
|
+
{
|
|
419
|
+
name: 'execute_workflow',
|
|
420
|
+
description: 'Load and execute a slash command workflow',
|
|
421
|
+
inputSchema: {
|
|
422
|
+
type: 'object',
|
|
423
|
+
properties: {
|
|
424
|
+
command: {
|
|
425
|
+
type: 'string',
|
|
426
|
+
description: 'Workflow command (e.g., /plan, /debug, /create)',
|
|
427
|
+
},
|
|
428
|
+
},
|
|
429
|
+
required: ['command'],
|
|
430
|
+
},
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
name: 'route_request',
|
|
434
|
+
description: 'Automatically route a user request to the best agent',
|
|
435
|
+
inputSchema: {
|
|
436
|
+
type: 'object',
|
|
437
|
+
properties: {
|
|
438
|
+
request: {
|
|
439
|
+
type: 'string',
|
|
440
|
+
description: 'The user request to analyze and route',
|
|
441
|
+
},
|
|
442
|
+
},
|
|
443
|
+
required: ['request'],
|
|
444
|
+
},
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
name: 'load_rules',
|
|
448
|
+
description: 'Load the base rules (GEMINI.md) for the toolkit',
|
|
449
|
+
inputSchema: {
|
|
450
|
+
type: 'object',
|
|
451
|
+
properties: {},
|
|
452
|
+
required: [],
|
|
453
|
+
},
|
|
454
|
+
},
|
|
455
|
+
],
|
|
456
|
+
};
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
460
|
+
const { name, arguments: args } = request.params;
|
|
461
|
+
|
|
462
|
+
try {
|
|
463
|
+
switch (name) {
|
|
464
|
+
case 'list_agents': {
|
|
465
|
+
const agents = await listAgents();
|
|
466
|
+
return {
|
|
467
|
+
content: [
|
|
468
|
+
{
|
|
469
|
+
type: 'text',
|
|
470
|
+
text: JSON.stringify(agents, null, 2),
|
|
471
|
+
},
|
|
472
|
+
],
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
case 'load_agent': {
|
|
477
|
+
const agent = await loadAgent(args.name);
|
|
478
|
+
return {
|
|
479
|
+
content: [
|
|
480
|
+
{
|
|
481
|
+
type: 'text',
|
|
482
|
+
text: JSON.stringify(agent, null, 2),
|
|
483
|
+
},
|
|
484
|
+
],
|
|
485
|
+
};
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
case 'list_skills': {
|
|
489
|
+
const skills = await listSkills();
|
|
490
|
+
return {
|
|
491
|
+
content: [
|
|
492
|
+
{
|
|
493
|
+
type: 'text',
|
|
494
|
+
text: JSON.stringify(skills, null, 2),
|
|
495
|
+
},
|
|
496
|
+
],
|
|
497
|
+
};
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
case 'load_skill': {
|
|
501
|
+
const skill = await loadSkill(args.name);
|
|
502
|
+
return {
|
|
503
|
+
content: [
|
|
504
|
+
{
|
|
505
|
+
type: 'text',
|
|
506
|
+
text: JSON.stringify(skill, null, 2),
|
|
507
|
+
},
|
|
508
|
+
],
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
case 'list_workflows': {
|
|
513
|
+
const workflows = await listWorkflows();
|
|
514
|
+
return {
|
|
515
|
+
content: [
|
|
516
|
+
{
|
|
517
|
+
type: 'text',
|
|
518
|
+
text: JSON.stringify(workflows, null, 2),
|
|
519
|
+
},
|
|
520
|
+
],
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
case 'execute_workflow': {
|
|
525
|
+
const workflow = await loadWorkflow(args.command);
|
|
526
|
+
return {
|
|
527
|
+
content: [
|
|
528
|
+
{
|
|
529
|
+
type: 'text',
|
|
530
|
+
text: JSON.stringify(workflow, null, 2),
|
|
531
|
+
},
|
|
532
|
+
],
|
|
533
|
+
};
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
case 'route_request': {
|
|
537
|
+
const agentName = await routeToAgent(args.request);
|
|
538
|
+
const agent = await loadAgent(agentName);
|
|
539
|
+
return {
|
|
540
|
+
content: [
|
|
541
|
+
{
|
|
542
|
+
type: 'text',
|
|
543
|
+
text: JSON.stringify({
|
|
544
|
+
selectedAgent: agentName,
|
|
545
|
+
reason: `Request matched keywords for ${agentName}`,
|
|
546
|
+
agent,
|
|
547
|
+
}, null, 2),
|
|
548
|
+
},
|
|
549
|
+
],
|
|
550
|
+
};
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
case 'load_rules': {
|
|
554
|
+
const rules = await loadRules();
|
|
555
|
+
return {
|
|
556
|
+
content: [
|
|
557
|
+
{
|
|
558
|
+
type: 'text',
|
|
559
|
+
text: JSON.stringify(rules, null, 2),
|
|
560
|
+
},
|
|
561
|
+
],
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
default:
|
|
566
|
+
return {
|
|
567
|
+
content: [
|
|
568
|
+
{
|
|
569
|
+
type: 'text',
|
|
570
|
+
text: `Unknown tool: ${name}`,
|
|
571
|
+
},
|
|
572
|
+
],
|
|
573
|
+
isError: true,
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
} catch (error) {
|
|
577
|
+
return {
|
|
578
|
+
content: [
|
|
579
|
+
{
|
|
580
|
+
type: 'text',
|
|
581
|
+
text: `Error: ${error.message}`,
|
|
582
|
+
},
|
|
583
|
+
],
|
|
584
|
+
isError: true,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
});
|
|
588
|
+
|
|
589
|
+
// ============================================================================
|
|
590
|
+
// RESOURCES
|
|
591
|
+
// ============================================================================
|
|
592
|
+
|
|
593
|
+
server.setRequestHandler(ListResourcesRequestSchema, async () => {
|
|
594
|
+
return {
|
|
595
|
+
resources: [
|
|
596
|
+
{
|
|
597
|
+
uri: 'antigravity://architecture',
|
|
598
|
+
name: 'Toolkit Architecture',
|
|
599
|
+
description: 'Complete architecture documentation for the Antigravity toolkit',
|
|
600
|
+
mimeType: 'text/markdown',
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
uri: 'antigravity://rules',
|
|
604
|
+
name: 'Base Rules',
|
|
605
|
+
description: 'GEMINI.md base rules (always active)',
|
|
606
|
+
mimeType: 'text/markdown',
|
|
607
|
+
},
|
|
608
|
+
],
|
|
609
|
+
};
|
|
610
|
+
});
|
|
611
|
+
|
|
612
|
+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
613
|
+
const { uri } = request.params;
|
|
614
|
+
|
|
615
|
+
switch (uri) {
|
|
616
|
+
case 'antigravity://architecture': {
|
|
617
|
+
const content = await readMarkdownFile(path.join(AGENT_ROOT, 'ARCHITECTURE.md'));
|
|
618
|
+
return {
|
|
619
|
+
contents: [
|
|
620
|
+
{
|
|
621
|
+
uri,
|
|
622
|
+
mimeType: 'text/markdown',
|
|
623
|
+
text: content || 'Architecture file not found',
|
|
624
|
+
},
|
|
625
|
+
],
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
case 'antigravity://rules': {
|
|
630
|
+
const rules = await loadRules();
|
|
631
|
+
return {
|
|
632
|
+
contents: [
|
|
633
|
+
{
|
|
634
|
+
uri,
|
|
635
|
+
mimeType: 'text/markdown',
|
|
636
|
+
text: rules.instructions || 'Rules file not found',
|
|
637
|
+
},
|
|
638
|
+
],
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
default:
|
|
643
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
644
|
+
}
|
|
645
|
+
});
|
|
646
|
+
|
|
647
|
+
// ============================================================================
|
|
648
|
+
// PROMPTS (Slash Commands as MCP Prompts)
|
|
649
|
+
// ============================================================================
|
|
650
|
+
|
|
651
|
+
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
652
|
+
const workflows = await listWorkflows();
|
|
653
|
+
|
|
654
|
+
return {
|
|
655
|
+
prompts: workflows.map((w) => ({
|
|
656
|
+
name: w.name,
|
|
657
|
+
description: w.description,
|
|
658
|
+
arguments: [
|
|
659
|
+
{
|
|
660
|
+
name: 'context',
|
|
661
|
+
description: 'Additional context for the workflow',
|
|
662
|
+
required: false,
|
|
663
|
+
},
|
|
664
|
+
],
|
|
665
|
+
})),
|
|
666
|
+
};
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
server.setRequestHandler(GetPromptRequestSchema, async (request) => {
|
|
670
|
+
const { name, arguments: args } = request.params;
|
|
671
|
+
|
|
672
|
+
const workflow = await loadWorkflow(name);
|
|
673
|
+
|
|
674
|
+
if (workflow.error) {
|
|
675
|
+
throw new Error(workflow.error);
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
const contextNote = args?.context ? `\n\nUser Context: ${args.context}` : '';
|
|
679
|
+
|
|
680
|
+
return {
|
|
681
|
+
description: workflow.frontmatter?.description || `Execute ${name} workflow`,
|
|
682
|
+
messages: [
|
|
683
|
+
{
|
|
684
|
+
role: 'user',
|
|
685
|
+
content: {
|
|
686
|
+
type: 'text',
|
|
687
|
+
text: `Execute the /${name} workflow.\n\n${workflow.instructions}${contextNote}`,
|
|
688
|
+
},
|
|
689
|
+
},
|
|
690
|
+
],
|
|
691
|
+
};
|
|
692
|
+
});
|
|
693
|
+
|
|
694
|
+
// ============================================================================
|
|
695
|
+
// START SERVER
|
|
696
|
+
// ============================================================================
|
|
697
|
+
|
|
698
|
+
async function main() {
|
|
699
|
+
const transport = new StdioServerTransport();
|
|
700
|
+
await server.connect(transport);
|
|
701
|
+
console.error('Antigravity Agent Toolkit MCP Server running');
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
main().catch(console.error);
|