@vizzly-testing/cli 0.23.1 → 0.23.2

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.
Files changed (36) hide show
  1. package/README.md +54 -586
  2. package/dist/api/client.js +3 -1
  3. package/dist/api/endpoints.js +6 -7
  4. package/dist/cli.js +15 -2
  5. package/dist/commands/finalize.js +12 -0
  6. package/dist/commands/preview.js +210 -28
  7. package/dist/commands/run.js +15 -0
  8. package/dist/commands/status.js +34 -8
  9. package/dist/commands/upload.js +13 -0
  10. package/package.json +1 -2
  11. package/claude-plugin/.claude-plugin/README.md +0 -270
  12. package/claude-plugin/.claude-plugin/marketplace.json +0 -28
  13. package/claude-plugin/.claude-plugin/plugin.json +0 -14
  14. package/claude-plugin/.mcp.json +0 -12
  15. package/claude-plugin/CHANGELOG.md +0 -85
  16. package/claude-plugin/commands/setup.md +0 -137
  17. package/claude-plugin/commands/suggest-screenshots.md +0 -111
  18. package/claude-plugin/mcp/vizzly-docs-server/README.md +0 -95
  19. package/claude-plugin/mcp/vizzly-docs-server/docs-fetcher.js +0 -110
  20. package/claude-plugin/mcp/vizzly-docs-server/index.js +0 -283
  21. package/claude-plugin/mcp/vizzly-server/cloud-api-provider.js +0 -399
  22. package/claude-plugin/mcp/vizzly-server/index.js +0 -927
  23. package/claude-plugin/mcp/vizzly-server/local-tdd-provider.js +0 -455
  24. package/claude-plugin/mcp/vizzly-server/token-resolver.js +0 -185
  25. package/claude-plugin/skills/check-visual-tests/SKILL.md +0 -158
  26. package/claude-plugin/skills/debug-visual-regression/SKILL.md +0 -269
  27. package/docs/api-reference.md +0 -1003
  28. package/docs/authentication.md +0 -334
  29. package/docs/doctor-command.md +0 -44
  30. package/docs/getting-started.md +0 -131
  31. package/docs/internal/SDK-API.md +0 -1018
  32. package/docs/plugins.md +0 -557
  33. package/docs/tdd-mode.md +0 -594
  34. package/docs/test-integration.md +0 -523
  35. package/docs/tui-elements.md +0 -560
  36. package/docs/upload-command.md +0 -196
@@ -1,95 +0,0 @@
1
- # Vizzly Docs MCP Server
2
-
3
- MCP server that provides Claude Code with easy access to Vizzly documentation.
4
-
5
- ## How It Works
6
-
7
- This server fetches documentation from the deployed `docs.vizzly.dev` site, making it easy for LLMs to:
8
- - Browse all available docs
9
- - Search documentation by keyword
10
- - Retrieve full markdown content
11
- - Understand the documentation structure
12
-
13
- ## Tools
14
-
15
- ### `list_docs`
16
- List all available documentation pages with optional category filtering.
17
-
18
- **Arguments:**
19
- - `category` (optional): Filter by category (e.g., "Integration > CLI", "Features")
20
-
21
- **Example:**
22
- ```javascript
23
- list_docs({ category: "CLI" })
24
- ```
25
-
26
- ### `get_doc`
27
- Get the full markdown content of a specific documentation page.
28
-
29
- **Arguments:**
30
- - `path` (required): The document path (e.g., "integration/cli/overview.mdx") or slug (e.g., "integration/cli/overview")
31
-
32
- **Example:**
33
- ```javascript
34
- get_doc({ path: "integration/cli/tdd-mode" })
35
- ```
36
-
37
- ### `search_docs`
38
- Search documentation by keyword. Searches in titles, descriptions, and categories.
39
-
40
- **Arguments:**
41
- - `query` (required): Search query
42
- - `limit` (optional): Maximum number of results (default: 10)
43
-
44
- **Example:**
45
- ```javascript
46
- search_docs({ query: "parallel builds", limit: 5 })
47
- ```
48
-
49
- ### `get_sidebar`
50
- Get the complete sidebar navigation structure.
51
-
52
- **Example:**
53
- ```javascript
54
- get_sidebar()
55
- ```
56
-
57
- ## Architecture
58
-
59
- The server works in a hybrid model:
60
- 1. **Index** - Fetches a pre-built JSON index from `docs.vizzly.dev/api/mcp-index.json`
61
- 2. **Content** - Fetches individual doc content on-demand from `docs.vizzly.dev/api/content/{path}`
62
- 3. **Caching** - Index is cached for 5 minutes to minimize network requests
63
-
64
- This approach ensures:
65
- - Fast browsing/searching (uses cached index)
66
- - Always up-to-date content (fetched from live site)
67
- - Minimal network overhead
68
- - No local file dependencies
69
-
70
- ## Data Flow
71
-
72
- ```
73
- Claude Code
74
-
75
- MCP Server (this)
76
-
77
- docs.vizzly.dev API
78
-
79
- Statically generated at build time (Astro)
80
- ```
81
-
82
- ## Development
83
-
84
- To test the server locally:
85
-
86
- ```bash
87
- # The server is automatically loaded by Claude Code when the plugin is active
88
- # Check .mcp.json for configuration
89
- ```
90
-
91
- ## Files
92
-
93
- - `index.js` - Main MCP server implementation
94
- - `docs-fetcher.js` - Utilities for fetching and searching docs
95
- - `README.md` - This file
@@ -1,110 +0,0 @@
1
- /**
2
- * Fetches documentation from docs.vizzly.dev
3
- */
4
-
5
- let BASE_URL = 'https://docs.vizzly.dev';
6
- let INDEX_URL = `${BASE_URL}/api/mcp-index.json`;
7
-
8
- /**
9
- * Fetch the documentation index
10
- */
11
- export async function fetchDocsIndex() {
12
- try {
13
- let response = await fetch(INDEX_URL);
14
-
15
- if (!response.ok) {
16
- throw new Error(`Failed to fetch docs index: ${response.status} ${response.statusText}`);
17
- }
18
-
19
- let index = await response.json();
20
- return index;
21
- } catch (error) {
22
- throw new Error(`Failed to load documentation index: ${error.message}`);
23
- }
24
- }
25
-
26
- /**
27
- * Fetch the content of a specific document
28
- */
29
- export async function fetchDocContent(path) {
30
- // Normalize path (remove leading slash, ensure it doesn't end with .md/.mdx)
31
- let cleanPath = path.replace(/^\//, '').replace(/\.(mdx?|md)$/, '');
32
-
33
- let contentUrl = `${BASE_URL}/api/content/${cleanPath}`;
34
-
35
- try {
36
- let response = await fetch(contentUrl);
37
-
38
- if (!response.ok) {
39
- // Try with .mdx extension if not found
40
- if (response.status === 404 && !path.endsWith('.mdx')) {
41
- contentUrl = `${BASE_URL}/api/content/${cleanPath}.mdx`;
42
- response = await fetch(contentUrl);
43
- }
44
-
45
- if (!response.ok) {
46
- throw new Error(`Document not found: ${path} (${response.status})`);
47
- }
48
- }
49
-
50
- let content = await response.text();
51
- return content;
52
- } catch (error) {
53
- throw new Error(`Failed to fetch document content: ${error.message}`);
54
- }
55
- }
56
-
57
- /**
58
- * Search documents by query
59
- * Simple client-side search through titles and descriptions
60
- */
61
- export function searchDocs(docs, query, limit = 10) {
62
- let lowerQuery = query.toLowerCase();
63
- let terms = lowerQuery.split(/\s+/);
64
-
65
- let results = docs
66
- .map(doc => {
67
- let titleLower = doc.title.toLowerCase();
68
- let descLower = (doc.description || '').toLowerCase();
69
- let categoryLower = doc.category.toLowerCase();
70
-
71
- let score = 0;
72
-
73
- // Exact phrase match in title (highest score)
74
- if (titleLower.includes(lowerQuery)) {
75
- score += 10;
76
- }
77
-
78
- // Exact phrase match in description
79
- if (descLower.includes(lowerQuery)) {
80
- score += 5;
81
- }
82
-
83
- // Exact phrase match in category
84
- if (categoryLower.includes(lowerQuery)) {
85
- score += 3;
86
- }
87
-
88
- // Individual term matches
89
- for (let term of terms) {
90
- if (titleLower.includes(term)) score += 3;
91
- if (descLower.includes(term)) score += 1;
92
- if (categoryLower.includes(term)) score += 0.5;
93
- }
94
-
95
- return { doc, score };
96
- })
97
- .filter(result => result.score > 0)
98
- .sort((a, b) => b.score - a.score)
99
- .slice(0, limit);
100
-
101
- // Normalize scores to 0-1 range
102
- if (results.length > 0) {
103
- let maxScore = results[0].score;
104
- for (let result of results) {
105
- result.score = result.score / maxScore;
106
- }
107
- }
108
-
109
- return results;
110
- }
@@ -1,283 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Vizzly Docs MCP Server
5
- * Provides Claude Code with easy access to Vizzly documentation
6
- *
7
- * This server fetches docs from the deployed docs.vizzly.dev site,
8
- * making it easy for LLMs to navigate and retrieve documentation content.
9
- */
10
-
11
- import { Server } from '@modelcontextprotocol/sdk/server/index.js';
12
- import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
13
- import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
14
- import { fetchDocsIndex, fetchDocContent, searchDocs } from './docs-fetcher.js';
15
-
16
- class VizzlyDocsMCPServer {
17
- constructor() {
18
- this.server = new Server(
19
- {
20
- name: 'vizzly-docs',
21
- version: '1.0.0'
22
- },
23
- {
24
- capabilities: {
25
- tools: {}
26
- }
27
- }
28
- );
29
-
30
- // Cache the index for the session
31
- this.indexCache = null;
32
- this.indexFetchTime = null;
33
- this.CACHE_TTL = 5 * 60 * 1000; // 5 minutes
34
-
35
- this.setupHandlers();
36
- }
37
-
38
- /**
39
- * Get the docs index (with caching)
40
- */
41
- async getIndex() {
42
- let now = Date.now();
43
-
44
- if (!this.indexCache || !this.indexFetchTime || now - this.indexFetchTime > this.CACHE_TTL) {
45
- this.indexCache = await fetchDocsIndex();
46
- this.indexFetchTime = now;
47
- }
48
-
49
- return this.indexCache;
50
- }
51
-
52
- setupHandlers() {
53
- // List available tools
54
- this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
55
- tools: [
56
- {
57
- name: 'list_docs',
58
- description:
59
- 'List all available Vizzly documentation pages. Returns title, description, category, and URL for each doc. Optionally filter by category.',
60
- inputSchema: {
61
- type: 'object',
62
- properties: {
63
- category: {
64
- type: 'string',
65
- description:
66
- 'Optional category filter (e.g., "Integration > CLI", "Features"). Case-insensitive partial match.'
67
- }
68
- }
69
- }
70
- },
71
- {
72
- name: 'get_doc',
73
- description:
74
- 'Get the full markdown content of a specific documentation page. Returns the raw MDX/markdown with frontmatter. Use the path or slug from list_docs.',
75
- inputSchema: {
76
- type: 'object',
77
- properties: {
78
- path: {
79
- type: 'string',
80
- description:
81
- 'The document path (e.g., "integration/cli/overview.mdx") or slug (e.g., "integration/cli/overview"). Get this from list_docs or search_docs.'
82
- }
83
- },
84
- required: ['path']
85
- }
86
- },
87
- {
88
- name: 'search_docs',
89
- description:
90
- 'Search documentation by keyword. Searches in titles and descriptions. Returns matching docs with relevance scores.',
91
- inputSchema: {
92
- type: 'object',
93
- properties: {
94
- query: {
95
- type: 'string',
96
- description: 'Search query (e.g., "TDD mode", "authentication", "parallel builds")'
97
- },
98
- limit: {
99
- type: 'number',
100
- description: 'Maximum number of results to return (default: 10)',
101
- default: 10
102
- }
103
- },
104
- required: ['query']
105
- }
106
- },
107
- {
108
- name: 'get_sidebar',
109
- description:
110
- 'Get the complete sidebar navigation structure. Useful for understanding how docs are organized and finding related pages.',
111
- inputSchema: {
112
- type: 'object',
113
- properties: {}
114
- }
115
- }
116
- ]
117
- }));
118
-
119
- // Handle tool calls
120
- this.server.setRequestHandler(CallToolRequestSchema, async request => {
121
- try {
122
- switch (request.params.name) {
123
- case 'list_docs':
124
- return await this.handleListDocs(request.params.arguments);
125
-
126
- case 'get_doc':
127
- return await this.handleGetDoc(request.params.arguments);
128
-
129
- case 'search_docs':
130
- return await this.handleSearchDocs(request.params.arguments);
131
-
132
- case 'get_sidebar':
133
- return await this.handleGetSidebar();
134
-
135
- default:
136
- throw new Error(`Unknown tool: ${request.params.name}`);
137
- }
138
- } catch (error) {
139
- return {
140
- content: [
141
- {
142
- type: 'text',
143
- text: `Error: ${error.message}`
144
- }
145
- ],
146
- isError: true
147
- };
148
- }
149
- });
150
- }
151
-
152
- async handleListDocs(args) {
153
- let index = await this.getIndex();
154
- let { category } = args || {};
155
-
156
- let docs = index.docs;
157
-
158
- // Filter by category if provided
159
- if (category) {
160
- let lowerCategory = category.toLowerCase();
161
- docs = docs.filter(doc => doc.category.toLowerCase().includes(lowerCategory));
162
- }
163
-
164
- // Format response
165
- let response = `# Vizzly Documentation (${docs.length} docs)\n\n`;
166
-
167
- if (category) {
168
- response += `Filtered by category: "${category}"\n\n`;
169
- }
170
-
171
- // Group by category
172
- let byCategory = {};
173
- for (let doc of docs) {
174
- if (!byCategory[doc.category]) {
175
- byCategory[doc.category] = [];
176
- }
177
- byCategory[doc.category].push(doc);
178
- }
179
-
180
- for (let [cat, catDocs] of Object.entries(byCategory)) {
181
- response += `## ${cat}\n\n`;
182
- for (let doc of catDocs) {
183
- response += `- **${doc.title}**\n`;
184
- response += ` - Path: \`${doc.path}\`\n`;
185
- response += ` - Slug: \`${doc.slug}\`\n`;
186
- if (doc.description) {
187
- response += ` - ${doc.description}\n`;
188
- }
189
- response += ` - URL: ${doc.url}\n\n`;
190
- }
191
- }
192
-
193
- return {
194
- content: [
195
- {
196
- type: 'text',
197
- text: response
198
- }
199
- ]
200
- };
201
- }
202
-
203
- async handleGetDoc(args) {
204
- let { path } = args;
205
-
206
- if (!path) {
207
- throw new Error('path parameter is required');
208
- }
209
-
210
- let content = await fetchDocContent(path);
211
-
212
- return {
213
- content: [
214
- {
215
- type: 'text',
216
- text: content
217
- }
218
- ]
219
- };
220
- }
221
-
222
- async handleSearchDocs(args) {
223
- let { query, limit = 10 } = args;
224
-
225
- if (!query) {
226
- throw new Error('query parameter is required');
227
- }
228
-
229
- let index = await this.getIndex();
230
- let results = searchDocs(index.docs, query, limit);
231
-
232
- let response = `# Search Results for "${query}"\n\n`;
233
- response += `Found ${results.length} matching docs:\n\n`;
234
-
235
- for (let result of results) {
236
- response += `## ${result.doc.title}\n`;
237
- response += `- **Category:** ${result.doc.category}\n`;
238
- response += `- **Path:** \`${result.doc.path}\`\n`;
239
- response += `- **Relevance:** ${Math.round(result.score * 100)}%\n`;
240
- if (result.doc.description) {
241
- response += `- **Description:** ${result.doc.description}\n`;
242
- }
243
- response += `- **URL:** ${result.doc.url}\n\n`;
244
- }
245
-
246
- return {
247
- content: [
248
- {
249
- type: 'text',
250
- text: response
251
- }
252
- ]
253
- };
254
- }
255
-
256
- async handleGetSidebar() {
257
- let index = await this.getIndex();
258
-
259
- let response = `# Vizzly Documentation Structure\n\n`;
260
- response += JSON.stringify(index.sidebar, null, 2);
261
-
262
- return {
263
- content: [
264
- {
265
- type: 'text',
266
- text: response
267
- }
268
- ]
269
- };
270
- }
271
-
272
- async run() {
273
- let transport = new StdioServerTransport();
274
- await this.server.connect(transport);
275
- }
276
- }
277
-
278
- // Start the server
279
- let server = new VizzlyDocsMCPServer();
280
- server.run().catch(error => {
281
- console.error('Server error:', error);
282
- process.exit(1);
283
- });