@tanstack/cli 0.60.1 → 0.62.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/dist/cli.js +266 -11
- package/dist/command-line.js +103 -8
- package/dist/discovery.js +144 -0
- package/dist/options.js +35 -2
- package/dist/types/command-line.d.ts +7 -0
- package/dist/types/{mcp/types.d.ts → discovery.d.ts} +23 -75
- package/dist/types/types.d.ts +1 -2
- package/dist/types/ui-prompts.d.ts +5 -0
- package/dist/ui-prompts.js +26 -0
- package/package.json +6 -5
- package/skills/CHANGELOG.md +18 -0
- package/skills/add-addons-existing-app/SKILL.md +113 -0
- package/skills/choose-ecosystem-integrations/SKILL.md +140 -0
- package/skills/choose-ecosystem-integrations/references/authentication-providers.md +19 -0
- package/skills/choose-ecosystem-integrations/references/data-layer-providers.md +20 -0
- package/skills/choose-ecosystem-integrations/references/deployment-targets.md +19 -0
- package/skills/create-app-scaffold/SKILL.md +132 -0
- package/skills/create-app-scaffold/references/create-flag-compatibility-matrix.md +34 -0
- package/skills/create-app-scaffold/references/deployment-providers.md +19 -0
- package/skills/create-app-scaffold/references/framework-adapters.md +17 -0
- package/skills/create-app-scaffold/references/toolchains.md +17 -0
- package/skills/maintain-custom-addons-dev-watch/SKILL.md +118 -0
- package/skills/query-docs-library-metadata/SKILL.md +85 -0
- package/skills/query-docs-library-metadata/references/discovery-command-output-schemas.md +70 -0
- package/CHANGELOG.md +0 -787
- package/dist/mcp/api.js +0 -31
- package/dist/mcp/tools.js +0 -250
- package/dist/mcp/types.js +0 -37
- package/dist/mcp.js +0 -181
- package/dist/types/mcp/api.d.ts +0 -4
- package/dist/types/mcp/tools.d.ts +0 -2
- package/dist/types/mcp.d.ts +0 -5
- package/playwright-report/index.html +0 -85
- package/playwright.config.ts +0 -21
- package/src/bin.ts +0 -15
- package/src/cli.ts +0 -767
- package/src/command-line.ts +0 -473
- package/src/dev-watch.ts +0 -564
- package/src/file-syncer.ts +0 -263
- package/src/index.ts +0 -21
- package/src/mcp/api.ts +0 -42
- package/src/mcp/tools.ts +0 -323
- package/src/mcp/types.ts +0 -46
- package/src/mcp.ts +0 -263
- package/src/options.ts +0 -234
- package/src/types.ts +0 -28
- package/src/ui-environment.ts +0 -74
- package/src/ui-prompts.ts +0 -355
- package/src/utils.ts +0 -30
- package/test-results/.last-run.json +0 -4
- package/tests/command-line.test.ts +0 -622
- package/tests/index.test.ts +0 -9
- package/tests/mcp.test.ts +0 -225
- package/tests/options.test.ts +0 -216
- package/tests/setupVitest.ts +0 -6
- package/tests/ui-environment.test.ts +0 -97
- package/tests/ui-prompts.test.ts +0 -205
- package/tests-e2e/addons-smoke.spec.ts +0 -31
- package/tests-e2e/create-smoke.spec.ts +0 -39
- package/tests-e2e/helpers.ts +0 -526
- package/tests-e2e/matrix-opportunistic.spec.ts +0 -142
- package/tests-e2e/router-only-smoke.spec.ts +0 -68
- package/tests-e2e/solid-smoke.spec.ts +0 -25
- package/tests-e2e/templates-smoke.spec.ts +0 -52
- package/tsconfig.json +0 -17
- package/vitest.config.js +0 -8
package/dist/mcp/api.js
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { LibrariesResponseSchema, PartnersResponseSchema } from './types.js';
|
|
2
|
-
const TANSTACK_API_BASE = 'https://tanstack.com/api/data';
|
|
3
|
-
export async function fetchLibraries() {
|
|
4
|
-
const response = await fetch(`${TANSTACK_API_BASE}/libraries`);
|
|
5
|
-
if (!response.ok) {
|
|
6
|
-
throw new Error(`Failed to fetch libraries: ${response.statusText}`);
|
|
7
|
-
}
|
|
8
|
-
const data = await response.json();
|
|
9
|
-
return LibrariesResponseSchema.parse(data);
|
|
10
|
-
}
|
|
11
|
-
export async function fetchPartners() {
|
|
12
|
-
const response = await fetch(`${TANSTACK_API_BASE}/partners`);
|
|
13
|
-
if (!response.ok) {
|
|
14
|
-
throw new Error(`Failed to fetch partners: ${response.statusText}`);
|
|
15
|
-
}
|
|
16
|
-
const data = await response.json();
|
|
17
|
-
return PartnersResponseSchema.parse(data);
|
|
18
|
-
}
|
|
19
|
-
export async function fetchDocContent(repo, branch, filePath) {
|
|
20
|
-
const url = `https://raw.githubusercontent.com/${repo}/${branch}/${filePath}`;
|
|
21
|
-
const response = await fetch(url, {
|
|
22
|
-
headers: { 'User-Agent': 'tanstack-cli' },
|
|
23
|
-
});
|
|
24
|
-
if (!response.ok) {
|
|
25
|
-
if (response.status === 404) {
|
|
26
|
-
return null;
|
|
27
|
-
}
|
|
28
|
-
throw new Error(`Failed to fetch doc: ${response.statusText}`);
|
|
29
|
-
}
|
|
30
|
-
return response.text();
|
|
31
|
-
}
|
package/dist/mcp/tools.js
DELETED
|
@@ -1,250 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { fetchDocContent, fetchLibraries, fetchPartners } from './api.js';
|
|
3
|
-
// Algolia config (public read-only keys)
|
|
4
|
-
const ALGOLIA_APP_ID = 'FQ0DQ6MA3C';
|
|
5
|
-
const ALGOLIA_API_KEY = '10c34d6a5c89f6048cf644d601e65172';
|
|
6
|
-
const ALGOLIA_INDEX = 'tanstack-test';
|
|
7
|
-
const GROUP_KEYS = ['state', 'headlessUI', 'performance', 'tooling'];
|
|
8
|
-
function jsonResult(data) {
|
|
9
|
-
return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] };
|
|
10
|
-
}
|
|
11
|
-
function errorResult(error) {
|
|
12
|
-
return { content: [{ type: 'text', text: `Error: ${error}` }], isError: true };
|
|
13
|
-
}
|
|
14
|
-
export function registerDocTools(server) {
|
|
15
|
-
// Tool: tanstack_list_libraries
|
|
16
|
-
server.tool('tanstack_list_libraries', 'List TanStack libraries with metadata, frameworks, and docs URLs.', {
|
|
17
|
-
group: z
|
|
18
|
-
.enum(GROUP_KEYS)
|
|
19
|
-
.optional()
|
|
20
|
-
.describe('Filter libraries by group. Options: state, headlessUI, performance, tooling'),
|
|
21
|
-
}, async ({ group }) => {
|
|
22
|
-
try {
|
|
23
|
-
const data = await fetchLibraries();
|
|
24
|
-
let libraries = data.libraries;
|
|
25
|
-
if (group && data.groups[group]) {
|
|
26
|
-
const groupIds = data.groups[group];
|
|
27
|
-
libraries = libraries.filter((lib) => groupIds.includes(lib.id));
|
|
28
|
-
}
|
|
29
|
-
const groupName = group ? data.groupNames[group] || group : 'All Libraries';
|
|
30
|
-
return jsonResult({
|
|
31
|
-
group: groupName,
|
|
32
|
-
count: libraries.length,
|
|
33
|
-
libraries: libraries.map((lib) => ({
|
|
34
|
-
id: lib.id,
|
|
35
|
-
name: lib.name,
|
|
36
|
-
tagline: lib.tagline,
|
|
37
|
-
description: lib.description,
|
|
38
|
-
frameworks: lib.frameworks,
|
|
39
|
-
latestVersion: lib.latestVersion,
|
|
40
|
-
docsUrl: lib.docsUrl,
|
|
41
|
-
githubUrl: lib.githubUrl,
|
|
42
|
-
})),
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
catch (error) {
|
|
46
|
-
return errorResult(String(error));
|
|
47
|
-
}
|
|
48
|
-
});
|
|
49
|
-
// Tool: tanstack_doc
|
|
50
|
-
server.tool('tanstack_doc', 'Fetch a TanStack documentation page by library and path.', {
|
|
51
|
-
library: z.string().describe('Library ID (e.g., query, router, table, form)'),
|
|
52
|
-
path: z.string().describe('Documentation path (e.g., framework/react/overview)'),
|
|
53
|
-
version: z.string().optional().describe('Version (e.g., v5, v1). Defaults to latest'),
|
|
54
|
-
}, async ({ library: libraryId, path, version = 'latest' }) => {
|
|
55
|
-
try {
|
|
56
|
-
const data = await fetchLibraries();
|
|
57
|
-
const library = data.libraries.find((l) => l.id === libraryId);
|
|
58
|
-
if (!library) {
|
|
59
|
-
return errorResult(`Library "${libraryId}" not found. Use tanstack_list_libraries to see available libraries.`);
|
|
60
|
-
}
|
|
61
|
-
if (version !== 'latest' && !library.availableVersions.includes(version)) {
|
|
62
|
-
return errorResult(`Version "${version}" not found for ${library.name}. Available: ${library.availableVersions.join(', ')}`);
|
|
63
|
-
}
|
|
64
|
-
// Resolve branch
|
|
65
|
-
const branch = version === 'latest' || version === library.latestVersion
|
|
66
|
-
? library.latestBranch || 'main'
|
|
67
|
-
: version;
|
|
68
|
-
const docsRoot = library.docsRoot || 'docs';
|
|
69
|
-
const filePath = `${docsRoot}/${path}.md`;
|
|
70
|
-
const content = await fetchDocContent(library.repo, branch, filePath);
|
|
71
|
-
if (!content) {
|
|
72
|
-
return errorResult(`Document not found: ${library.name} / ${path} (version: ${version})`);
|
|
73
|
-
}
|
|
74
|
-
// Extract frontmatter title if present
|
|
75
|
-
const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
|
|
76
|
-
let title = path.split('/').pop() || 'Untitled';
|
|
77
|
-
let docContent = content;
|
|
78
|
-
if (frontmatterMatch && frontmatterMatch[1]) {
|
|
79
|
-
const frontmatter = frontmatterMatch[1];
|
|
80
|
-
const titleMatch = frontmatter.match(/title:\s*['"]?([^'"\n]+)['"]?/);
|
|
81
|
-
if (titleMatch && titleMatch[1]) {
|
|
82
|
-
title = titleMatch[1];
|
|
83
|
-
}
|
|
84
|
-
docContent = content.slice(frontmatterMatch[0].length).trim();
|
|
85
|
-
}
|
|
86
|
-
return jsonResult({
|
|
87
|
-
title,
|
|
88
|
-
content: docContent,
|
|
89
|
-
url: `https://tanstack.com/${libraryId}/${version}/docs/${path}`,
|
|
90
|
-
library: library.name,
|
|
91
|
-
version: version === 'latest' ? library.latestVersion : version,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
catch (error) {
|
|
95
|
-
return errorResult(String(error));
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
// Tool: tanstack_search_docs
|
|
99
|
-
server.tool('tanstack_search_docs', 'Search TanStack documentation. Returns matching pages with snippets.', {
|
|
100
|
-
query: z.string().describe('Search query'),
|
|
101
|
-
library: z.string().optional().describe('Filter to specific library (e.g., query, router)'),
|
|
102
|
-
framework: z
|
|
103
|
-
.string()
|
|
104
|
-
.optional()
|
|
105
|
-
.describe('Filter to specific framework (e.g., react, vue, solid)'),
|
|
106
|
-
limit: z
|
|
107
|
-
.number()
|
|
108
|
-
.min(1)
|
|
109
|
-
.max(50)
|
|
110
|
-
.optional()
|
|
111
|
-
.describe('Maximum number of results (default: 10, max: 50)'),
|
|
112
|
-
}, async ({ query, library, framework, limit = 10 }) => {
|
|
113
|
-
try {
|
|
114
|
-
const ALL_LIBRARIES = [
|
|
115
|
-
'config', 'form', 'optimistic', 'pacer', 'query', 'ranger',
|
|
116
|
-
'react-charts', 'router', 'start', 'store', 'table', 'virtual', 'db', 'devtools',
|
|
117
|
-
];
|
|
118
|
-
const ALL_FRAMEWORKS = ['react', 'vue', 'solid', 'svelte', 'angular'];
|
|
119
|
-
// Build filters
|
|
120
|
-
const filterParts = ['version:latest'];
|
|
121
|
-
if (library) {
|
|
122
|
-
const otherLibraries = ALL_LIBRARIES.filter((l) => l !== library);
|
|
123
|
-
const exclusions = otherLibraries.map((l) => `NOT library:${l}`).join(' AND ');
|
|
124
|
-
if (exclusions)
|
|
125
|
-
filterParts.push(`(${exclusions})`);
|
|
126
|
-
}
|
|
127
|
-
if (framework) {
|
|
128
|
-
const otherFrameworks = ALL_FRAMEWORKS.filter((f) => f !== framework);
|
|
129
|
-
const exclusions = otherFrameworks.map((f) => `NOT framework:${f}`).join(' AND ');
|
|
130
|
-
if (exclusions)
|
|
131
|
-
filterParts.push(`(${exclusions})`);
|
|
132
|
-
}
|
|
133
|
-
// Call Algolia REST API directly
|
|
134
|
-
const searchParams = {
|
|
135
|
-
requests: [
|
|
136
|
-
{
|
|
137
|
-
indexName: ALGOLIA_INDEX,
|
|
138
|
-
query,
|
|
139
|
-
hitsPerPage: Math.min(limit, 50),
|
|
140
|
-
filters: filterParts.join(' AND '),
|
|
141
|
-
attributesToRetrieve: ['hierarchy', 'url', 'content', 'library'],
|
|
142
|
-
attributesToSnippet: ['content:80'],
|
|
143
|
-
},
|
|
144
|
-
],
|
|
145
|
-
};
|
|
146
|
-
const response = await fetch(`https://${ALGOLIA_APP_ID}-dsn.algolia.net/1/indexes/*/queries`, {
|
|
147
|
-
method: 'POST',
|
|
148
|
-
headers: {
|
|
149
|
-
'Content-Type': 'application/json',
|
|
150
|
-
'X-Algolia-Application-Id': ALGOLIA_APP_ID,
|
|
151
|
-
'X-Algolia-API-Key': ALGOLIA_API_KEY,
|
|
152
|
-
},
|
|
153
|
-
body: JSON.stringify(searchParams),
|
|
154
|
-
});
|
|
155
|
-
if (!response.ok) {
|
|
156
|
-
return errorResult(`Algolia search failed: ${response.statusText}`);
|
|
157
|
-
}
|
|
158
|
-
const searchResponse = await response.json();
|
|
159
|
-
const searchResult = searchResponse.results[0];
|
|
160
|
-
if (!searchResult) {
|
|
161
|
-
return jsonResult({ query, totalHits: 0, results: [] });
|
|
162
|
-
}
|
|
163
|
-
const results = searchResult.hits.map((hit) => {
|
|
164
|
-
const breadcrumb = Object.values(hit.hierarchy).filter((v) => Boolean(v));
|
|
165
|
-
return {
|
|
166
|
-
title: hit.hierarchy.lvl1 || hit.hierarchy.lvl0 || 'Untitled',
|
|
167
|
-
url: hit.url,
|
|
168
|
-
snippet: hit._snippetResult?.content?.value || hit.content || '',
|
|
169
|
-
library: hit.library || 'unknown',
|
|
170
|
-
breadcrumb,
|
|
171
|
-
};
|
|
172
|
-
});
|
|
173
|
-
return jsonResult({
|
|
174
|
-
query,
|
|
175
|
-
totalHits: searchResult.nbHits || results.length,
|
|
176
|
-
results,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
catch (error) {
|
|
180
|
-
return errorResult(String(error));
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
// Tool: tanstack_ecosystem
|
|
184
|
-
server.tool('tanstack_ecosystem', 'Ecosystem partner recommendations. Filter by category (database, auth, deployment, monitoring, cms, api, data-grid) or library.', {
|
|
185
|
-
category: z
|
|
186
|
-
.string()
|
|
187
|
-
.optional()
|
|
188
|
-
.describe('Filter by category: database, auth, deployment, monitoring, cms, api, data-grid, code-review, learning'),
|
|
189
|
-
library: z
|
|
190
|
-
.string()
|
|
191
|
-
.optional()
|
|
192
|
-
.describe('Filter by TanStack library (e.g., start, router, query, table)'),
|
|
193
|
-
}, async ({ category, library }) => {
|
|
194
|
-
try {
|
|
195
|
-
const data = await fetchPartners();
|
|
196
|
-
// Category aliases
|
|
197
|
-
const categoryAliases = {
|
|
198
|
-
db: 'database',
|
|
199
|
-
postgres: 'database',
|
|
200
|
-
sql: 'database',
|
|
201
|
-
login: 'auth',
|
|
202
|
-
authentication: 'auth',
|
|
203
|
-
hosting: 'deployment',
|
|
204
|
-
deploy: 'deployment',
|
|
205
|
-
serverless: 'deployment',
|
|
206
|
-
errors: 'monitoring',
|
|
207
|
-
logging: 'monitoring',
|
|
208
|
-
content: 'cms',
|
|
209
|
-
'api-keys': 'api',
|
|
210
|
-
grid: 'data-grid',
|
|
211
|
-
review: 'code-review',
|
|
212
|
-
courses: 'learning',
|
|
213
|
-
};
|
|
214
|
-
let resolvedCategory;
|
|
215
|
-
if (category) {
|
|
216
|
-
const normalized = category.toLowerCase().trim();
|
|
217
|
-
resolvedCategory = categoryAliases[normalized] || normalized;
|
|
218
|
-
if (!data.categories.includes(resolvedCategory)) {
|
|
219
|
-
resolvedCategory = undefined;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
const lib = library?.toLowerCase().trim();
|
|
223
|
-
const partners = data.partners
|
|
224
|
-
.filter((p) => !resolvedCategory || p.category === resolvedCategory)
|
|
225
|
-
.filter((p) => !lib || p.libraries.some((l) => l === lib))
|
|
226
|
-
.map((p) => ({
|
|
227
|
-
id: p.id,
|
|
228
|
-
name: p.name,
|
|
229
|
-
tagline: p.tagline,
|
|
230
|
-
description: p.description,
|
|
231
|
-
category: p.category,
|
|
232
|
-
categoryLabel: p.categoryLabel,
|
|
233
|
-
url: p.url,
|
|
234
|
-
libraries: p.libraries,
|
|
235
|
-
}));
|
|
236
|
-
return jsonResult({
|
|
237
|
-
query: {
|
|
238
|
-
category,
|
|
239
|
-
categoryResolved: resolvedCategory,
|
|
240
|
-
library,
|
|
241
|
-
},
|
|
242
|
-
count: partners.length,
|
|
243
|
-
partners,
|
|
244
|
-
});
|
|
245
|
-
}
|
|
246
|
-
catch (error) {
|
|
247
|
-
return errorResult(String(error));
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
}
|
package/dist/mcp/types.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
// API response types from tanstack.com
|
|
3
|
-
export const LibrarySchema = z.object({
|
|
4
|
-
id: z.string(),
|
|
5
|
-
name: z.string(),
|
|
6
|
-
tagline: z.string(),
|
|
7
|
-
description: z.string().optional(),
|
|
8
|
-
frameworks: z.array(z.string()),
|
|
9
|
-
latestVersion: z.string(),
|
|
10
|
-
latestBranch: z.string().optional(),
|
|
11
|
-
availableVersions: z.array(z.string()),
|
|
12
|
-
repo: z.string(),
|
|
13
|
-
docsRoot: z.string().optional(),
|
|
14
|
-
defaultDocs: z.string().optional(),
|
|
15
|
-
docsUrl: z.string().optional(),
|
|
16
|
-
githubUrl: z.string().optional(),
|
|
17
|
-
});
|
|
18
|
-
export const LibrariesResponseSchema = z.object({
|
|
19
|
-
libraries: z.array(LibrarySchema),
|
|
20
|
-
groups: z.record(z.array(z.string())),
|
|
21
|
-
groupNames: z.record(z.string()),
|
|
22
|
-
});
|
|
23
|
-
export const PartnerSchema = z.object({
|
|
24
|
-
id: z.string(),
|
|
25
|
-
name: z.string(),
|
|
26
|
-
tagline: z.string().optional(),
|
|
27
|
-
description: z.string(),
|
|
28
|
-
category: z.string(),
|
|
29
|
-
categoryLabel: z.string(),
|
|
30
|
-
libraries: z.array(z.string()),
|
|
31
|
-
url: z.string(),
|
|
32
|
-
});
|
|
33
|
-
export const PartnersResponseSchema = z.object({
|
|
34
|
-
partners: z.array(PartnerSchema),
|
|
35
|
-
categories: z.array(z.string()),
|
|
36
|
-
categoryLabels: z.record(z.string()),
|
|
37
|
-
});
|
package/dist/mcp.js
DELETED
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
2
|
-
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
-
import express from 'express';
|
|
5
|
-
import { z } from 'zod';
|
|
6
|
-
import { createApp, createDefaultEnvironment, finalizeAddOns, getFrameworkByName, getFrameworks, populateAddOnOptionsDefaults, } from '@tanstack/create';
|
|
7
|
-
import { registerDocTools } from './mcp/tools.js';
|
|
8
|
-
function createServer({ appName, forcedAddOns = [], }) {
|
|
9
|
-
const server = new McpServer({
|
|
10
|
-
name: `${appName} Application Builder`,
|
|
11
|
-
version: '1.0.0',
|
|
12
|
-
});
|
|
13
|
-
const frameworks = getFrameworks();
|
|
14
|
-
const frameworkNames = frameworks.map((framework) => framework.name);
|
|
15
|
-
server.tool('listTanStackAddOns', 'List the available add-ons for creating TanStack applications', {
|
|
16
|
-
framework: z
|
|
17
|
-
.string()
|
|
18
|
-
.describe(`The framework to use. Available frameworks: ${frameworkNames.join(', ')}`),
|
|
19
|
-
}, ({ framework: frameworkName }) => {
|
|
20
|
-
const framework = getFrameworkByName(frameworkName);
|
|
21
|
-
return {
|
|
22
|
-
content: [
|
|
23
|
-
{
|
|
24
|
-
type: 'text',
|
|
25
|
-
text: JSON.stringify(framework
|
|
26
|
-
.getAddOns()
|
|
27
|
-
.filter((addOn) => addOn.modes.includes('file-router'))
|
|
28
|
-
.map((addOn) => ({
|
|
29
|
-
id: addOn.id,
|
|
30
|
-
name: addOn.name,
|
|
31
|
-
description: addOn.description,
|
|
32
|
-
type: addOn.type,
|
|
33
|
-
category: addOn.category,
|
|
34
|
-
link: addOn.link,
|
|
35
|
-
warning: addOn.warning,
|
|
36
|
-
exclusive: addOn.exclusive,
|
|
37
|
-
options: addOn.options,
|
|
38
|
-
dependsOn: addOn.dependsOn,
|
|
39
|
-
}))),
|
|
40
|
-
},
|
|
41
|
-
],
|
|
42
|
-
};
|
|
43
|
-
});
|
|
44
|
-
server.tool('getAddOnDetails', 'Get detailed information about a specific add-on including implementation patterns, routes, dependencies, and documentation', {
|
|
45
|
-
framework: z
|
|
46
|
-
.string()
|
|
47
|
-
.describe(`The framework to use. Available frameworks: ${frameworkNames.join(', ')}`),
|
|
48
|
-
addOnId: z
|
|
49
|
-
.string()
|
|
50
|
-
.describe('The ID of the add-on to get details for'),
|
|
51
|
-
}, async ({ framework: frameworkName, addOnId }) => {
|
|
52
|
-
const framework = getFrameworkByName(frameworkName);
|
|
53
|
-
const allAddOns = framework.getAddOns();
|
|
54
|
-
const addOn = allAddOns.find((a) => a.id === addOnId) ??
|
|
55
|
-
allAddOns.find((a) => a.id.toLowerCase() === addOnId.toLowerCase());
|
|
56
|
-
if (!addOn) {
|
|
57
|
-
return {
|
|
58
|
-
content: [
|
|
59
|
-
{
|
|
60
|
-
type: 'text',
|
|
61
|
-
text: JSON.stringify({ error: `Add-on '${addOnId}' not found` }),
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
// Get file list for context
|
|
67
|
-
const files = await addOn.getFiles();
|
|
68
|
-
return {
|
|
69
|
-
content: [
|
|
70
|
-
{
|
|
71
|
-
type: 'text',
|
|
72
|
-
text: JSON.stringify({
|
|
73
|
-
id: addOn.id,
|
|
74
|
-
name: addOn.name,
|
|
75
|
-
description: addOn.description,
|
|
76
|
-
type: addOn.type,
|
|
77
|
-
category: addOn.category,
|
|
78
|
-
phase: addOn.phase,
|
|
79
|
-
modes: addOn.modes,
|
|
80
|
-
link: addOn.link,
|
|
81
|
-
warning: addOn.warning,
|
|
82
|
-
exclusive: addOn.exclusive,
|
|
83
|
-
dependsOn: addOn.dependsOn,
|
|
84
|
-
options: addOn.options,
|
|
85
|
-
routes: addOn.routes,
|
|
86
|
-
packageAdditions: addOn.packageAdditions,
|
|
87
|
-
shadcnComponents: addOn.shadcnComponents,
|
|
88
|
-
integrations: addOn.integrations,
|
|
89
|
-
readme: addOn.readme,
|
|
90
|
-
files,
|
|
91
|
-
author: addOn.author,
|
|
92
|
-
version: addOn.version,
|
|
93
|
-
license: addOn.license,
|
|
94
|
-
}),
|
|
95
|
-
},
|
|
96
|
-
],
|
|
97
|
-
};
|
|
98
|
-
});
|
|
99
|
-
server.tool('createTanStackApplication', 'Create a new TanStack application', {
|
|
100
|
-
framework: z
|
|
101
|
-
.string()
|
|
102
|
-
.describe(`The framework to use. Available frameworks: ${frameworkNames.join(', ')}`),
|
|
103
|
-
projectName: z
|
|
104
|
-
.string()
|
|
105
|
-
.describe('The package.json module name of the application (will also be the directory name)'),
|
|
106
|
-
cwd: z.string().describe('The directory to create the application in'),
|
|
107
|
-
addOns: z.array(z.string()).describe('Array of add-on IDs to install. Use listTanStackAddOns tool to see available add-ons and their configuration options. Example: ["prisma", "shadcn", "tanstack-query"]'),
|
|
108
|
-
addOnOptions: z.record(z.record(z.any())).optional().describe('Configuration options for add-ons. Format: {"addOnId": {"optionName": "value"}}. Use listTanStackAddOns to see available options for each add-on.'),
|
|
109
|
-
targetDir: z
|
|
110
|
-
.string()
|
|
111
|
-
.describe('The directory to create the application in. Use the absolute path of the directory you want the application to be created in'),
|
|
112
|
-
}, async ({ framework: frameworkName, projectName, addOns, addOnOptions, cwd, targetDir, }) => {
|
|
113
|
-
const framework = getFrameworkByName(frameworkName);
|
|
114
|
-
try {
|
|
115
|
-
process.chdir(cwd);
|
|
116
|
-
try {
|
|
117
|
-
const chosenAddOns = await finalizeAddOns(framework, 'file-router', Array.from(new Set([
|
|
118
|
-
...addOns,
|
|
119
|
-
...forcedAddOns,
|
|
120
|
-
])));
|
|
121
|
-
await createApp(createDefaultEnvironment(), {
|
|
122
|
-
projectName: projectName.replace(/^\//, './'),
|
|
123
|
-
targetDir,
|
|
124
|
-
framework,
|
|
125
|
-
typescript: true,
|
|
126
|
-
tailwind: true,
|
|
127
|
-
packageManager: 'pnpm',
|
|
128
|
-
mode: 'file-router',
|
|
129
|
-
chosenAddOns,
|
|
130
|
-
addOnOptions: addOnOptions || populateAddOnOptionsDefaults(chosenAddOns),
|
|
131
|
-
git: true,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
catch (error) {
|
|
135
|
-
console.error(error);
|
|
136
|
-
return {
|
|
137
|
-
content: [
|
|
138
|
-
{ type: 'text', text: `Error creating application: ${error}` },
|
|
139
|
-
],
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
return {
|
|
143
|
-
content: [{ type: 'text', text: 'Application created successfully' }],
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
catch (error) {
|
|
147
|
-
return {
|
|
148
|
-
content: [
|
|
149
|
-
{ type: 'text', text: `Error creating application: ${error}` },
|
|
150
|
-
],
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
});
|
|
154
|
-
// Register doc/ecosystem tools from TanStack API
|
|
155
|
-
registerDocTools(server);
|
|
156
|
-
return server;
|
|
157
|
-
}
|
|
158
|
-
export async function runMCPServer(sse, { forcedAddOns, appName, name, }) {
|
|
159
|
-
let transport = null;
|
|
160
|
-
const server = createServer({ appName, forcedAddOns, name });
|
|
161
|
-
if (sse) {
|
|
162
|
-
const app = express();
|
|
163
|
-
app.get('/sse', (req, res) => {
|
|
164
|
-
transport = new SSEServerTransport('/messages', res);
|
|
165
|
-
server.connect(transport);
|
|
166
|
-
});
|
|
167
|
-
app.post('/messages', (req, res) => {
|
|
168
|
-
if (transport) {
|
|
169
|
-
transport.handlePostMessage(req, res);
|
|
170
|
-
}
|
|
171
|
-
});
|
|
172
|
-
const port = process.env.PORT || 8080;
|
|
173
|
-
app.listen(port, () => {
|
|
174
|
-
console.log(`Server is running on port http://localhost:${port}/sse`);
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
else {
|
|
178
|
-
const transport = new StdioServerTransport();
|
|
179
|
-
await server.connect(transport);
|
|
180
|
-
}
|
|
181
|
-
}
|
package/dist/types/mcp/api.d.ts
DELETED
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import type { LibrariesResponse, PartnersResponse } from './types.js';
|
|
2
|
-
export declare function fetchLibraries(): Promise<LibrariesResponse>;
|
|
3
|
-
export declare function fetchPartners(): Promise<PartnersResponse>;
|
|
4
|
-
export declare function fetchDocContent(repo: string, branch: string, filePath: string): Promise<string | null>;
|