mirror of
https://github.com/sveltejs/ai-tools.git
synced 2026-07-04 03:19:38 +08:00
Compare commits
39 Commits
@sveltejs/
...
@sveltejs/
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9a74df198d | ||
|
|
f1280b9876 | ||
|
|
132943db3b | ||
|
|
5ed1454e2c | ||
|
|
bd072bd324 | ||
|
|
c35be898da | ||
|
|
b960301ced | ||
|
|
43408f5504 | ||
|
|
bf4dcda7e1 | ||
|
|
35691c464b | ||
|
|
a5decb4cf3 | ||
|
|
cb9764c234 | ||
|
|
3fbc786383 | ||
|
|
3b680232a0 | ||
|
|
c5c08ccd13 | ||
|
|
4ac35bf258 | ||
|
|
ecbbf70d98 | ||
|
|
aaac49cdef | ||
|
|
558d964919 | ||
|
|
73d7625b3c | ||
|
|
c7060c8bdb | ||
|
|
ef2d569934 | ||
|
|
7ba57b45ae | ||
|
|
fe393bf480 | ||
|
|
a63deba99d | ||
|
|
668a2e4481 | ||
|
|
04c82875f3 | ||
|
|
84601f9ab0 | ||
|
|
e01a050017 | ||
|
|
5920f7482f | ||
|
|
fa90a2be8d | ||
|
|
73bf0c3782 | ||
|
|
11cd2447fc | ||
|
|
8483bd672d | ||
|
|
8414ffbcc8 | ||
|
|
5798b50ceb | ||
|
|
e560932211 | ||
|
|
9504e6bac9 | ||
|
|
7086e8e55f |
2
.github/workflows/check.yml
vendored
2
.github/workflows/check.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.18.0
|
||||
version: 10.18.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.18.0
|
||||
version: 10.18.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
|
||||
37
.github/workflows/publish-mcp.yml
vendored
Normal file
37
.github/workflows/publish-mcp.yml
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
name: Publish to MCP Registry
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
permissions:
|
||||
id-token: write # OpenID Connect token needed for MCP registry authentication
|
||||
|
||||
jobs:
|
||||
publish-mcp:
|
||||
name: Publish to MCP Registry
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Publish to MCP Registry
|
||||
working-directory: packages/mcp-stdio
|
||||
run: |
|
||||
NAME=mcp-publisher_1.2.3_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz
|
||||
# Download MCP Publisher pinned to v1.2.3 using latest https for security and save it to a file named mcp-publisher.tar.gz
|
||||
curl --proto '=https' --proto-redir '=https' --tlsv1.2 -fL "https://github.com/modelcontextprotocol/registry/releases/download/v1.2.3/$NAME" -O
|
||||
|
||||
# Verify the SHA256 checksum of the downloaded file
|
||||
sha256sum --ignore-missing -c ./checksums/registry_1.2.3_checksums.txt
|
||||
|
||||
# Extract the tarball
|
||||
tar -xzf $NAME --no-same-owner --no-same-permissions -C tmp
|
||||
|
||||
# Install the MCP Publisher binary
|
||||
install -m 0755 tmp/mcp-publisher
|
||||
|
||||
# Login using GitHub OIDC
|
||||
./mcp-publisher login github-oidc
|
||||
|
||||
# Publish to MCP Registry
|
||||
./mcp-publisher publish
|
||||
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
@@ -16,6 +16,8 @@ jobs:
|
||||
if: github.repository == 'sveltejs/mcp'
|
||||
name: Release
|
||||
runs-on: ${{ matrix.os }}
|
||||
outputs:
|
||||
published: ${{ steps.changesets.outputs.published }}
|
||||
strategy:
|
||||
matrix:
|
||||
# pseudo-matrix for convenience, NEVER use more than a single combination
|
||||
@@ -51,8 +53,17 @@ jobs:
|
||||
# pinned for security, always review third party action code before updating
|
||||
uses: changesets/action@e0145edc7d9d8679003495b11f87bd8ef63c0cba # v1.5.3
|
||||
with:
|
||||
# This expects you to have a script called changeset:version version that calls changeset version and updated what it needs to be updated
|
||||
version: pnpm changeset:version
|
||||
# This expects you to have a script called release which does a build for your packages and calls changeset publish
|
||||
publish: pnpm release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
||||
|
||||
publish-mcp:
|
||||
needs: release
|
||||
if: needs.release.outputs.published == 'true'
|
||||
permissions:
|
||||
id-token: write
|
||||
uses: ./.github/workflows/publish-mcp.yml
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.18.0
|
||||
version: 10.18.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
|
||||
@@ -13,7 +13,7 @@ The setup varies based on the version of the MCP you prefer — remote or local
|
||||
|
||||
## Usage
|
||||
|
||||
To get the most out of the MCP server we recommend including the following prompt in your `AGENTS.md` (or `CLAUDE.md`, if using Claude Code). This will tell the LLM which tools are available and when it's appropriate to use them.
|
||||
To get the most out of the MCP server we recommend including the following prompt in your [`AGENTS.md`](https://agents.md) (or [`CLAUDE.md`](https://docs.claude.com/en/docs/claude-code/memory#claude-md-imports), if using Claude Code). This will tell the LLM which tools are available and when it's appropriate to use them.
|
||||
|
||||
```md
|
||||
You are able to use the Svelte MCP server, where you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
|
||||
|
||||
@@ -15,7 +15,7 @@ Here's how to set it up in some common MCP clients:
|
||||
To include the local MCP version in Claude Code, simply run the following command:
|
||||
|
||||
```bash
|
||||
claude mcp add -t stdio -s [scope] svelte npx -y @sveltejs/mcp
|
||||
claude mcp add -t stdio -s [scope] svelte -- npx -y @sveltejs/mcp
|
||||
```
|
||||
|
||||
The `[scope]` must be `user`, `project` or `local`.
|
||||
@@ -108,6 +108,25 @@ It will open a file with your MCP servers where you can add the following config
|
||||
}
|
||||
```
|
||||
|
||||
## Zed
|
||||
|
||||
- Open the command palette
|
||||
- Search and select "agent:open settings"
|
||||
- In settings panel look for `Model Context Protocol (MCP) Servers`
|
||||
- Click on "Add Server"
|
||||
- Select: "Add Custom Server"
|
||||
|
||||
It will open a popup with MCP server config where you can add the following configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"svelte": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sveltejs/mcp"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Other clients
|
||||
|
||||
If we didn't include the MCP client you are using, refer to their documentation for `stdio` servers and use `npx` as the command and `-y @sveltejs/mcp` as the arguments.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "The official Svelte MCP server implementation",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.18.0",
|
||||
"packageManager": "pnpm@10.18.1",
|
||||
"scripts": {
|
||||
"build": "pnpm -r run build",
|
||||
"dev": "pnpm --filter @sveltejs/mcp-remote run dev",
|
||||
@@ -18,7 +18,8 @@
|
||||
"inspect": "pnpm mcp-inspector",
|
||||
"generate-summaries": "pnpm --filter @sveltejs/mcp-server run generate-summaries",
|
||||
"debug:generate-summaries": "pnpm --filter @sveltejs/mcp-server run debug:generate-summaries",
|
||||
"release": "pnpm --filter @sveltejs/mcp run build && changeset publish"
|
||||
"release": "pnpm --filter @sveltejs/mcp run build && changeset publish",
|
||||
"changeset:version": "changeset version && pnpm --filter @sveltejs/mcp run update:version && git add --all"
|
||||
},
|
||||
"keywords": [
|
||||
"svelte",
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,36 @@ describe('add_autofixers_issues', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should add a suggestion when calling a function inside an effect', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import { fetch_data } from './data.js';
|
||||
$effect(() => {
|
||||
fetch_data();
|
||||
});
|
||||
</script>`);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
`You are calling the function \`fetch_data\` inside an $effect. Please check if the function is reassigning a stateful variable because that's considered malpractice and check if it could use \`$derived\` instead. Ignore this suggestion if you are sure this function is not assigning any stateful variable or if you can't check if it does.`,
|
||||
);
|
||||
});
|
||||
|
||||
it('should add a suggestion when calling a function inside an effect (with non identifier callee)', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import { fetch_data } from './data.js';
|
||||
$effect(() => {
|
||||
fetch_data.fetch();
|
||||
});
|
||||
</script>`);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
`You are calling a function inside an $effect. Please check if the function is reassigning a stateful variable because that's considered malpractice and check if it could use \`$derived\` instead. Ignore this suggestion if you are sure this function is not assigning any stateful variable or if you can't check if it does.`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
with_possible_inits('($init)', ({ init }) => {
|
||||
@@ -484,4 +514,177 @@ describe('add_autofixers_issues', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('suggest_attachments', () => {
|
||||
describe('bind:this', () => {
|
||||
it('should add suggestions when using bind:this on an element', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
let a = $state();
|
||||
</script>
|
||||
|
||||
<a bind:this={a} />`);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action` or even better an `attachment`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using bind:this on a component', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import Child from './Child.svelte';
|
||||
let a = $state();
|
||||
</script>
|
||||
|
||||
<Child bind:this={a} />`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action` or even better an `attachment`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using bind:this on a component nested in an element', () => {
|
||||
const content = run_autofixers_on_code(`
|
||||
<script>
|
||||
import Child from './Child.svelte';
|
||||
let a = $state();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Child bind:this={a} />
|
||||
</div>`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action` or even better an `attachment`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions but not suggest attachments when using bind:this on an element and the desired svelte version is 4', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`
|
||||
<script>
|
||||
let a;
|
||||
</script>
|
||||
|
||||
<a bind:this={a} />`,
|
||||
4,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'The usage of `bind:this` can often be replaced with an easier to read `action`. Consider using the latter if possible.',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('use:', () => {
|
||||
it('should add suggestions when using use: on an element and the action is declared as a function', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
function my_action(node) {
|
||||
// do something with the node
|
||||
}
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions when using use: on an element and the action is declared as a variable', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
const my_action = (node) => {
|
||||
// do something with the node
|
||||
}
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions when using use: on an element and the action is declared as an object', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
const my_action = {
|
||||
action: (node) => {
|
||||
// do something with the node
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<a use:my_action.action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions.length).toBeGreaterThanOrEqual(1);
|
||||
expect(content.suggestions).toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the desired svelte version is 4', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
function my_action(node) {
|
||||
// do something with the node
|
||||
}
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
4,
|
||||
);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the action comes from an import', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
import { my_action } from './actions.js';
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the action comes from the props', () => {
|
||||
const content = run_autofixers_on_code(
|
||||
`<script>
|
||||
const { my_action } = $props();
|
||||
</script>
|
||||
|
||||
<a use:my_action />`,
|
||||
);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
|
||||
it('should not add suggestions when using use: on an element and the action comes from a global variable', () => {
|
||||
const content = run_autofixers_on_code(`<a use:my_action />`);
|
||||
|
||||
expect(content.suggestions).not.toContain(
|
||||
'Consider using an `attachment` instead of an `action` for "my_action".',
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import type { AssignmentExpression, Identifier, Node, UpdateExpression } from 'estree';
|
||||
import type {
|
||||
AssignmentExpression,
|
||||
CallExpression,
|
||||
Identifier,
|
||||
Node,
|
||||
UpdateExpression,
|
||||
} from 'estree';
|
||||
import type { Autofixer, AutofixerState } from './index.js';
|
||||
import { left_most_id } from '../ast/utils.js';
|
||||
import type { AST } from 'svelte-eslint-parser';
|
||||
@@ -19,9 +25,9 @@ function run_if_in_effect(
|
||||
}
|
||||
}
|
||||
|
||||
function visitor(
|
||||
function assign_or_update_visitor(
|
||||
node: UpdateExpression | AssignmentExpression,
|
||||
{ state, path }: Context<Node | AST.SvelteNode, AutofixerState>,
|
||||
{ state, path, next }: Context<Node | AST.SvelteNode, AutofixerState>,
|
||||
) {
|
||||
run_if_in_effect(path, state, () => {
|
||||
function check_if_stateful_id(id: Identifier) {
|
||||
@@ -50,9 +56,25 @@ function visitor(
|
||||
}
|
||||
}
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
function call_expression_visitor(
|
||||
node: CallExpression,
|
||||
{ state, path, next }: Context<Node | AST.SvelteNode, AutofixerState>,
|
||||
) {
|
||||
run_if_in_effect(path, state, () => {
|
||||
const function_name =
|
||||
node.callee.type === 'Identifier' ? `the function \`${node.callee.name}\`` : 'a function';
|
||||
state.output.suggestions.push(
|
||||
`You are calling ${function_name} inside an $effect. Please check if the function is reassigning a stateful variable because that's considered malpractice and check if it could use \`$derived\` instead. Ignore this suggestion if you are sure this function is not assigning any stateful variable or if you can't check if it does.`,
|
||||
);
|
||||
});
|
||||
next();
|
||||
}
|
||||
|
||||
export const assign_in_effect: Autofixer = {
|
||||
UpdateExpression: visitor,
|
||||
AssignmentExpression: visitor,
|
||||
UpdateExpression: assign_or_update_visitor,
|
||||
AssignmentExpression: assign_or_update_visitor,
|
||||
CallExpression: call_expression_visitor,
|
||||
};
|
||||
|
||||
@@ -16,3 +16,4 @@ export * from './wrong-property-access-state.js';
|
||||
export * from './imported-runes.js';
|
||||
export * from './derived-with-function.js';
|
||||
export * from './use-runes-instead-of-store.js';
|
||||
export * from './suggest-attachments.js';
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
import type { Identifier } from 'estree';
|
||||
import type { Autofixer } from './index.js';
|
||||
import { left_most_id } from '../ast/utils.js';
|
||||
|
||||
export const suggest_attachments: Autofixer = {
|
||||
SvelteDirective(node, { state, next, path }) {
|
||||
if (node.kind === 'Binding' && node.key.name.name === 'this') {
|
||||
const parent_element = path.findLast((p) => p.type === 'SvelteElement');
|
||||
if (parent_element?.kind === 'html' && parent_element.startTag.attributes.includes(node)) {
|
||||
let better_an_attachment = ` or even better an \`attachment\``;
|
||||
if (state.desired_svelte_version === 4) {
|
||||
better_an_attachment = ``;
|
||||
}
|
||||
state.output.suggestions.push(
|
||||
`The usage of \`bind:this\` can often be replaced with an easier to read \`action\`${better_an_attachment}. Consider using the latter if possible.`,
|
||||
);
|
||||
}
|
||||
} else if (node.kind === 'Action' && state.desired_svelte_version === 5) {
|
||||
let id: Identifier | null = null;
|
||||
if (node.key.name.type === 'Identifier') {
|
||||
id = node.key.name;
|
||||
} else if (node.key.name.type === 'MemberExpression') {
|
||||
id = left_most_id(node.key.name);
|
||||
}
|
||||
if (id) {
|
||||
const reference = state.parsed.find_reference_by_id(id);
|
||||
const definition = reference?.resolved?.defs[0];
|
||||
console.log(definition);
|
||||
if (
|
||||
definition &&
|
||||
(definition.type === 'Variable' ||
|
||||
!(definition.type === 'ImportBinding' || definition.type === 'Parameter')) &&
|
||||
!(
|
||||
definition.type === 'Variable' &&
|
||||
definition.node.init?.type === 'CallExpression' &&
|
||||
state.parsed.is_rune(definition.node.init, ['$props'])
|
||||
)
|
||||
) {
|
||||
state.output.suggestions.push(
|
||||
`Consider using an \`attachment\` instead of an \`action\` for "${id.name}".`,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
next();
|
||||
},
|
||||
};
|
||||
@@ -1,5 +1,29 @@
|
||||
# @sveltejs/mcp
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- feat: publish mcp to registry (maybe for real this time) ([`132943d`](https://github.com/sveltejs/mcp/commit/132943db3b04dbbd322d08926c0880c990a61f5f))
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- feat: publish to registry ([#45](https://github.com/sveltejs/mcp/pull/45))
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- feat: add autofixer to tell the LLM to check if some function called in effect is assigning state #26 ([`73d7625`](https://github.com/sveltejs/mcp/commit/73d7625b3ca6a812ba91883ea668d80ff1e7c703))
|
||||
|
||||
- feat: add bind:this -> attachment and action -> attachment autofixer #20 ([`73d7625`](https://github.com/sveltejs/mcp/commit/73d7625b3ca6a812ba91883ea668d80ff1e7c703))
|
||||
|
||||
## 0.0.4
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: allow TS `.svelte.ts` modules ([#49](https://github.com/sveltejs/mcp/pull/49))
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
25
packages/mcp-stdio/checksums/registry_1.2.3_checksums.txt
Normal file
25
packages/mcp-stdio/checksums/registry_1.2.3_checksums.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
4e7c92f289d903d4649c59f82df6e7b014caebb49d8b5c1d2466667fd6caf68c mcp-publisher_1.2.3_darwin_amd64.tar.gz
|
||||
09637600871bec7cce25e098d6ce23b7c7577a8e537f618d24a5630d2d782afa mcp-publisher_1.2.3_darwin_amd64.tar.gz.sbom.json
|
||||
9ac90d3182bae9af4b48fb3cd19c3cade3e52c8ea25d7aa14327326a209bcf71 mcp-publisher_1.2.3_darwin_arm64.tar.gz
|
||||
0b2cedf3f42c5a7b33bdd3f72ce7f4c938ff4fe2aca5cabd60094dc4b855c1f6 mcp-publisher_1.2.3_darwin_arm64.tar.gz.sbom.json
|
||||
868a54268f21580ec97ec9dfc4fc3442a7f69c241ee7c745c7032f2e43cdf47b mcp-publisher_1.2.3_linux_amd64.tar.gz
|
||||
a7bce190ea1c1b5682d1b5069b20dd9c67f3688e02dbc93e7273e942097dac4d mcp-publisher_1.2.3_linux_amd64.tar.gz.sbom.json
|
||||
319cdefb4c4f19fa35eeb0337e30be3169dbf3107a8c160651691a6342a6783b mcp-publisher_1.2.3_linux_arm64.tar.gz
|
||||
bc9309ab843531e811990dcf637b9912c470fc38eddc13a5af0512fcef498944 mcp-publisher_1.2.3_linux_arm64.tar.gz.sbom.json
|
||||
298026e0252547046f50dcb7817239d44107f5a3ae64f4e43b6a31d0c5b89f9b mcp-publisher_1.2.3_windows_amd64.tar.gz
|
||||
971b835ce4df2b37ddcf8591d4400dc94d1e3f730b181b325c905261b75b9e6e mcp-publisher_1.2.3_windows_amd64.tar.gz.sbom.json
|
||||
64da67b451d0fba12f15f7b0f6ab8d71c718bb2263f90f198ff1fe15a5ff2024 mcp-publisher_1.2.3_windows_arm64.tar.gz
|
||||
f591b2153f1277cb67817763a23de9e77188fa94b893fac00e91d13160d696e3 mcp-publisher_1.2.3_windows_arm64.tar.gz.sbom.json
|
||||
265377b343500898e3c3fea798926ff2695fe7500c1225c8a97f390a5892d849 registry-1.2.3.tar.gz
|
||||
a9c03a84d2e30176d6ed7b493e7e3a8a05d446f1611a35bad6007fbe3ba80657 registry_1.2.3_darwin_amd64.tar.gz
|
||||
4db4e8a0b1f3d0ca193e5356fef89b74c0666cdf56d6f3c8fc2d0aba1cac3b55 registry_1.2.3_darwin_amd64.tar.gz.sbom.json
|
||||
2933a11990db16035e4896f394ada389166046911e6868f79b84636048dfe6fb registry_1.2.3_darwin_arm64.tar.gz
|
||||
edd36e62f4b1c5b857da1862f20cbcf6dd3dfd9717888c08bd5c25740d8b11f6 registry_1.2.3_darwin_arm64.tar.gz.sbom.json
|
||||
59bdd9977795891220e6fdb8f79dd7d14f48166362e94699bee59e745f7c7df6 registry_1.2.3_linux_amd64.tar.gz
|
||||
7f7efb180aa312f674377e32a92ac3600e50c62e37d697d2d16acfe60227a2fd registry_1.2.3_linux_amd64.tar.gz.sbom.json
|
||||
7fef1088a664850dd75e54a699fce6a5fb32e8ebbdc0d2869b6b34945727ba9c registry_1.2.3_linux_arm64.tar.gz
|
||||
ca0488e5cbb04c8ee515e1b80e08b755a55d6af1784368a2f55e429137359a25 registry_1.2.3_linux_arm64.tar.gz.sbom.json
|
||||
5bc29310aacc08437dcc973cfc1e1129f7065d2050396012f5ed98c4eb0ea75b registry_1.2.3_windows_amd64.tar.gz
|
||||
e918c604f23e6d33f9952f18eddf0e50e50d7ce3e87ca5258bf78f4f1da243ab registry_1.2.3_windows_amd64.tar.gz.sbom.json
|
||||
394cad1e6f5e37a583defdd522edbff854de5035d6e025a195664db31b58c0c0 registry_1.2.3_windows_arm64.tar.gz
|
||||
c93df66f3257ba4b9c29f7bfded4cf04d712ec220b044ddfa019da3e4bd6475f registry_1.2.3_windows_arm64.tar.gz.sbom.json
|
||||
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "@sveltejs/mcp",
|
||||
"version": "0.0.3",
|
||||
"version": "0.1.1",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"mcpName": "io.github.sveltejs/svelte",
|
||||
"homepage": "https://github.com/sveltejs/mcp#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sveltejs/mcp/issues"
|
||||
@@ -26,7 +27,8 @@
|
||||
"dev": "tsdown --watch",
|
||||
"test": "vitest",
|
||||
"check": "tsc --noEmit",
|
||||
"check:publint": "publint --strict"
|
||||
"check:publint": "publint --strict",
|
||||
"update:version": "node scripts/update-version.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/mcp-server": "workspace:^",
|
||||
|
||||
14
packages/mcp-stdio/scripts/update-version.ts
Normal file
14
packages/mcp-stdio/scripts/update-version.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { resolve } from 'node:path';
|
||||
|
||||
const package_json_string = await readFile(resolve('./package.json'), 'utf-8');
|
||||
const package_json = JSON.parse(package_json_string);
|
||||
|
||||
const server_json_path = resolve('./server.json');
|
||||
const server_json_string = await readFile(server_json_path, 'utf-8');
|
||||
const server_json = JSON.parse(server_json_string);
|
||||
|
||||
server_json.version = package_json.version;
|
||||
server_json.packages[0].version = package_json.version;
|
||||
|
||||
await writeFile(server_json_path, JSON.stringify(server_json, null, '\t') + '\n', 'utf-8');
|
||||
30
packages/mcp-stdio/server.json
Normal file
30
packages/mcp-stdio/server.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
|
||||
"name": "io.github.sveltejs/svelte",
|
||||
"description": "The official Svelte MCP server providing docs and autofixing tools for Svelte development",
|
||||
"repository": {
|
||||
"id": "1054419133",
|
||||
"url": "https://github.com/sveltejs/mcp",
|
||||
"subfolder": "packages/mcp-stdio",
|
||||
"source": "github"
|
||||
},
|
||||
"version": "0.1.1",
|
||||
"websiteUrl": "https://svelte.dev/docs/mcp/overview",
|
||||
"packages": [
|
||||
{
|
||||
"registryType": "npm",
|
||||
"identifier": "@sveltejs/mcp",
|
||||
"version": "0.1.1",
|
||||
"runtimeHint": "npx",
|
||||
"transport": {
|
||||
"type": "stdio"
|
||||
}
|
||||
}
|
||||
],
|
||||
"remotes": [
|
||||
{
|
||||
"url": "https://mcp.svelte.dev/mcp",
|
||||
"type": "streamable-http"
|
||||
}
|
||||
]
|
||||
}
|
||||
11
pnpm-lock.yaml
generated
11
pnpm-lock.yaml
generated
@@ -177,6 +177,9 @@ importers:
|
||||
tmcp:
|
||||
specifier: ^1.13.0
|
||||
version: 1.14.0(typescript@5.9.2)
|
||||
ts-blank-space:
|
||||
specifier: ^0.6.2
|
||||
version: 0.6.2
|
||||
typescript-eslint:
|
||||
specifier: ^8.44.0
|
||||
version: 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
|
||||
@@ -3719,6 +3722,10 @@ packages:
|
||||
peerDependencies:
|
||||
typescript: '>=4.8.4'
|
||||
|
||||
ts-blank-space@0.6.2:
|
||||
resolution: {integrity: sha512-hZjcHdHrveEKI67v8OzI90a1bizgoDkY7ekE4fH89qJhZgxvmjfBOv98aibCU7OpKbvV3R9p/qd3DrzZqT1cFQ==}
|
||||
engines: {node: '>=18.0.0'}
|
||||
|
||||
ts-node@10.9.2:
|
||||
resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==}
|
||||
hasBin: true
|
||||
@@ -7586,6 +7593,10 @@ snapshots:
|
||||
dependencies:
|
||||
typescript: 5.9.2
|
||||
|
||||
ts-blank-space@0.6.2:
|
||||
dependencies:
|
||||
typescript: 5.9.2
|
||||
|
||||
ts-node@10.9.2(@types/node@24.5.2)(typescript@5.9.2):
|
||||
dependencies:
|
||||
'@cspotcode/source-map-support': 0.8.1
|
||||
|
||||
Reference in New Issue
Block a user