mirror of
https://github.com/sveltejs/ai-tools.git
synced 2026-07-04 11:42:22 +08:00
Compare commits
20 Commits
llms-txt
...
@sveltejs/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e01a050017 | ||
|
|
5920f7482f | ||
|
|
fa90a2be8d | ||
|
|
73bf0c3782 | ||
|
|
8785ad224c | ||
|
|
75e676d928 | ||
|
|
5b16bdd80b | ||
|
|
f3ee4ed59c | ||
|
|
725f785766 | ||
|
|
485e60e245 | ||
|
|
480bfca557 | ||
|
|
06f9fc6d63 | ||
|
|
f1f85d2445 | ||
|
|
b9c0a011e2 | ||
|
|
b92dd95dee | ||
|
|
99537cfa25 | ||
|
|
f93a6cee60 | ||
|
|
e8989db548 | ||
|
|
cb316c5b3e | ||
|
|
7c762109b6 |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@sveltejs/mcp': patch
|
||||
---
|
||||
|
||||
feat: `use_cases` documentation metadata
|
||||
6
.github/workflows/check.yml
vendored
6
.github/workflows/check.yml
vendored
@@ -13,15 +13,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.17.1
|
||||
version: 10.18.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/lint.yml
vendored
6
.github/workflows/lint.yml
vendored
@@ -13,15 +13,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.17.1
|
||||
version: 10.18.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'pnpm'
|
||||
|
||||
6
.github/workflows/test.yml
vendored
6
.github/workflows/test.yml
vendored
@@ -13,15 +13,15 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.17.1
|
||||
version: 10.18.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '22'
|
||||
cache: 'pnpm'
|
||||
|
||||
@@ -39,15 +39,15 @@
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@eslint/js": "^9.36.0",
|
||||
"@libsql/client": "^0.14.0",
|
||||
"@modelcontextprotocol/inspector": "^0.16.7",
|
||||
"@libsql/client": "^0.15.0",
|
||||
"@modelcontextprotocol/inspector": "^0.17.0",
|
||||
"@sveltejs/adapter-vercel": "^5.6.3",
|
||||
"@sveltejs/kit": "^2.22.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||
"@types/node": "^24.3.1",
|
||||
"@typescript-eslint/parser": "^8.44.0",
|
||||
"drizzle-kit": "^0.30.2",
|
||||
"drizzle-orm": "^0.40.0",
|
||||
"drizzle-kit": "^0.31.0",
|
||||
"drizzle-orm": "^0.44.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
"eslint-plugin-svelte": "^3.12.3",
|
||||
"globals": "^16.0.0",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "The official Svelte MCP server implementation",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.17.1",
|
||||
"packageManager": "pnpm@10.18.0",
|
||||
"scripts": {
|
||||
"build": "pnpm -r run build",
|
||||
"dev": "pnpm --filter @sveltejs/mcp-remote run dev",
|
||||
@@ -31,7 +31,7 @@
|
||||
"@changesets/cli": "^2.29.7",
|
||||
"@eslint/compat": "^1.3.2",
|
||||
"@eslint/js": "^9.36.0",
|
||||
"@modelcontextprotocol/inspector": "^0.16.7",
|
||||
"@modelcontextprotocol/inspector": "^0.17.0",
|
||||
"@svitejs/changesets-changelog-github-compact": "^1.2.0",
|
||||
"eslint": "^9.36.0",
|
||||
"eslint-config-prettier": "^10.0.1",
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
"license": "ISC",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "^0.40.1"
|
||||
"drizzle-orm": "^0.44.0"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"drizzle-orm": "^0.40.0"
|
||||
"drizzle-orm": "^0.44.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/mcp-schema": "workspace:^",
|
||||
@@ -28,6 +28,7 @@
|
||||
"svelte": "^5.39.2",
|
||||
"svelte-eslint-parser": "^1.3.2",
|
||||
"tmcp": "^1.13.0",
|
||||
"ts-blank-space": "^0.6.2",
|
||||
"typescript-eslint": "^8.44.0",
|
||||
"valibot": "^1.1.0",
|
||||
"vitest": "^3.2.4",
|
||||
@@ -35,10 +36,10 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@anthropic-ai/sdk": "^0.65.0",
|
||||
"dotenv": "^17.2.3",
|
||||
"@sveltejs/kit": "^2.42.2",
|
||||
"@types/eslint-scope": "^8.3.2",
|
||||
"@types/estree": "^1.0.8",
|
||||
"@typescript-eslint/types": "^8.44.0"
|
||||
"@typescript-eslint/types": "^8.44.0",
|
||||
"dotenv": "^17.2.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ describe('add_autofixers_issues', () => {
|
||||
<script>
|
||||
const count = ${init}(0);
|
||||
</script>
|
||||
|
||||
|
||||
<button onclick={() => count = 43}>Increment</button>
|
||||
`);
|
||||
|
||||
@@ -74,7 +74,7 @@ describe('add_autofixers_issues', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
const count = 0;
|
||||
|
||||
|
||||
$effect(() => {
|
||||
count = 43;
|
||||
});
|
||||
@@ -89,7 +89,7 @@ describe('add_autofixers_issues', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let count = ${init}(0);
|
||||
|
||||
|
||||
$effect(() => {
|
||||
count++;
|
||||
});
|
||||
@@ -105,7 +105,7 @@ describe('add_autofixers_issues', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let count = ${init}({ value: 0 });
|
||||
|
||||
|
||||
$effect(() => {
|
||||
count.value = 42;
|
||||
});
|
||||
@@ -116,6 +116,22 @@ describe('add_autofixers_issues', () => {
|
||||
'The stateful variable "count" is assigned inside an $effect which is generally consider a malpractice. Consider using $derived if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it(`should add a suggestion for variables that are mutated within an effect.pre`, () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let count = ${init}({ value: 0 });
|
||||
|
||||
$effect.pre(() => {
|
||||
count.value = 42;
|
||||
});
|
||||
</script>
|
||||
`);
|
||||
|
||||
expect(content.suggestions).toContain(
|
||||
'The stateful variable "count" is assigned inside an $effect which is generally consider a malpractice. Consider using $derived if possible.',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { compile } from 'svelte/compiler';
|
||||
import { compile as compile_component, compileModule } from 'svelte/compiler';
|
||||
import { extname } from 'path';
|
||||
import ts from 'ts-blank-space';
|
||||
|
||||
export function add_compile_issues(
|
||||
content: { issues: string[]; suggestions: string[] },
|
||||
@@ -6,6 +8,21 @@ export function add_compile_issues(
|
||||
desired_svelte_version: number,
|
||||
filename = 'Component.svelte',
|
||||
) {
|
||||
let compile = compile_component;
|
||||
const extension = extname(filename);
|
||||
if (extension !== '.svelte') {
|
||||
compile = compileModule;
|
||||
// compile module doesn't accept .ts files so we need to transpile them first with ts-blank-space
|
||||
// a fast and lightweight typescript transpiler that can strips types replacing them with white spaces
|
||||
// so the code positions are not affected
|
||||
if (extension === '.ts') {
|
||||
code = ts(code, (node) => {
|
||||
content.issues.push(
|
||||
`The provided file is a module but it contains invalid TypeScript code: ${node.getText()} at ${node.getStart()}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
const compilation_result = compile(code, {
|
||||
filename: filename || 'Component.svelte',
|
||||
generate: false,
|
||||
|
||||
@@ -12,7 +12,7 @@ function base_config(svelte_config: Config): ESLint.Options['baseConfig'] {
|
||||
return [
|
||||
...svelte.configs.recommended,
|
||||
{
|
||||
files: ['*.svelte'],
|
||||
files: ['*.svelte', '*.svelte.ts', '*.svelte.js'],
|
||||
rules: {
|
||||
'no-self-assign': 'warn',
|
||||
'svelte/infinite-reactive-loop': 'warn',
|
||||
|
||||
@@ -11,19 +11,11 @@ function run_if_in_effect(
|
||||
) {
|
||||
const in_effect = path.findLast(
|
||||
(node) =>
|
||||
node.type === 'CallExpression' &&
|
||||
node.callee.type === 'Identifier' &&
|
||||
node.callee.name === '$effect',
|
||||
node.type === 'CallExpression' && state.parsed.is_rune(node, ['$effect', '$effect.pre']),
|
||||
);
|
||||
|
||||
if (
|
||||
in_effect &&
|
||||
in_effect.type === 'CallExpression' &&
|
||||
(in_effect.callee.type === 'Identifier' || in_effect.callee.type === 'MemberExpression')
|
||||
) {
|
||||
if (state.parsed.is_rune(in_effect, ['$effect', '$effect.pre'])) {
|
||||
to_run();
|
||||
}
|
||||
if (in_effect) {
|
||||
to_run();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ export function setup_svelte_task(server: SvelteMcp) {
|
||||
server.prompt(
|
||||
{
|
||||
name: 'svelte-task-prompt',
|
||||
title: 'Svelte Task Prompt',
|
||||
title: 'Svelte-Task-Prompt',
|
||||
description:
|
||||
'Use this Prompt to ask for any svelte related task. It will automatically instruct the LLM on how to best use the autofixer and how to query for documentation pages.',
|
||||
schema: v.object({
|
||||
|
||||
@@ -6,7 +6,7 @@ export async function list_sections(server: SvelteMcp) {
|
||||
|
||||
server.template(
|
||||
{
|
||||
name: 'Svelte Doc Section',
|
||||
name: 'Svelte-Doc-Section',
|
||||
description: 'A single documentation section',
|
||||
list() {
|
||||
return sections.map((section) => {
|
||||
|
||||
@@ -7,7 +7,6 @@ export function get_documentation(server: SvelteMcp) {
|
||||
server.tool(
|
||||
{
|
||||
name: 'get-documentation',
|
||||
enabled: () => false,
|
||||
description:
|
||||
'Retrieves full documentation content for Svelte 5 or SvelteKit sections. Supports flexible search by title (e.g., "$state", "routing") or file path (e.g., "cli/overview"). Can accept a single section name or an array of sections. Before running this, make sure to analyze the users query, as well as the output from list-sections (which should be called first). Then ask for ALL relevant sections the user might require. For example, if the user asks to build anything interactive, you will need to fetch all relevant runes, and so on.',
|
||||
schema: v.object({
|
||||
|
||||
@@ -6,7 +6,6 @@ export function list_sections(server: SvelteMcp) {
|
||||
server.tool(
|
||||
{
|
||||
name: 'list-sections',
|
||||
enabled: () => false,
|
||||
description:
|
||||
'Lists all available Svelte 5 and SvelteKit documentation sections in a structured format. Each section includes a "use_cases" field that describes WHEN this documentation would be useful. You should carefully analyze the use_cases field to determine which sections are relevant for the user\'s query. The use_cases contain comma-separated keywords describing project types (e.g., "e-commerce", "blog"), features (e.g., "authentication", "forms"), components (e.g., "slider", "modal"), development stages (e.g., "deployment", "testing"), or "always" for fundamental concepts. Match these use_cases against the user\'s intent - for example, if building an e-commerce site, fetch sections with use_cases containing "e-commerce", "product listings", "shopping cart", etc. If building a slider, look for "slider", "carousel", "animation", etc. Returns sections as "* title: [section_title], use_cases: [use_cases], path: [file_path]". Always run list-sections FIRST for any Svelte query, then analyze ALL use_cases to identify relevant sections, and finally use get_documentation to fetch ALL relevant sections at once.',
|
||||
},
|
||||
|
||||
@@ -1,5 +1,23 @@
|
||||
# @sveltejs/mcp
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: allow TS `.svelte.ts` modules ([#49](https://github.com/sveltejs/mcp/pull/49))
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: check effect.pre in assign-in-effect ([#41](https://github.com/sveltejs/mcp/pull/41))
|
||||
|
||||
- feat: `use_cases` documentation metadata ([#29](https://github.com/sveltejs/mcp/pull/29))
|
||||
|
||||
- fix: change title names to allow for claude code to use the prompt ([`725f785`](https://github.com/sveltejs/mcp/commit/725f785766d04e9ed810a7c3f6bcfdb2e2b8234c))
|
||||
|
||||
- fix: enable doc tools ([`cb316c5`](https://github.com/sveltejs/mcp/commit/cb316c5b3ebc712946969d2d57236d159e796d58))
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sveltejs/mcp",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.4",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/sveltejs/mcp#readme",
|
||||
@@ -33,7 +33,7 @@
|
||||
"@tmcp/transport-stdio": "^0.3.1",
|
||||
"@types/node": "^22.15.17",
|
||||
"publint": "^0.3.13",
|
||||
"tsdown": "^0.11.9",
|
||||
"tsdown": "^0.15.0",
|
||||
"typescript": "^5.8.3",
|
||||
"vitest": "^3.1.3"
|
||||
},
|
||||
|
||||
661
pnpm-lock.yaml
generated
661
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user