mirror of
https://github.com/sveltejs/ai-tools.git
synced 2026-07-08 05:40:56 +08:00
Compare commits
11 Commits
@sveltejs/
...
patch-1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17ed3a3e23 | ||
|
|
f49bd06fbd | ||
|
|
b98c042ae3 | ||
|
|
917a93d3fd | ||
|
|
371e96befc | ||
|
|
bdfd5a109f | ||
|
|
1c6c0a9fa7 | ||
|
|
a321244543 | ||
|
|
ed25933466 | ||
|
|
e639e3ad5c | ||
|
|
d0bed3e8f0 |
5
.changeset/seven-breads-stay.md
Normal file
5
.changeset/seven-breads-stay.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@sveltejs/mcp': patch
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: suggest against js variables in css
|
||||||
3
.github/workflows/publish-mcp.yml
vendored
3
.github/workflows/publish-mcp.yml
vendored
@@ -5,6 +5,7 @@ on:
|
|||||||
secrets:
|
secrets:
|
||||||
MCP_KEY:
|
MCP_KEY:
|
||||||
required: true
|
required: true
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
publish-mcp:
|
publish-mcp:
|
||||||
@@ -19,7 +20,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
MCP_KEY: ${{ secrets.MCP_KEY }}
|
MCP_KEY: ${{ secrets.MCP_KEY }}
|
||||||
run: |
|
run: |
|
||||||
NAME=mcp-publisher_1.3.3_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz
|
NAME=mcp-publisher_$(uname -s | tr '[:upper:]' '[:lower:]')_$(uname -m | sed 's/x86_64/amd64/;s/aarch64/arm64/').tar.gz
|
||||||
# Download MCP Publisher pinned to v1.3.3 using latest https for security and save it to a file named mcp-publisher.tar.gz
|
# Download MCP Publisher pinned to v1.3.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.3.3/$NAME" -O
|
curl --proto '=https' --proto-redir '=https' --tlsv1.2 -fL "https://github.com/modelcontextprotocol/registry/releases/download/v1.3.3/$NAME" -O
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/mcp-schema": "workspace:^",
|
"@sveltejs/mcp-schema": "workspace:^",
|
||||||
"@sveltejs/mcp-server": "workspace:^",
|
"@sveltejs/mcp-server": "workspace:^",
|
||||||
"@tmcp/transport-http": "^0.6.3",
|
"@tmcp/transport-http": "^0.7.0",
|
||||||
"tmcp": "^1.15.0"
|
"tmcp": "^1.15.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ import { HttpTransport } from '@tmcp/transport-http';
|
|||||||
|
|
||||||
export const http_transport = new HttpTransport(server, {
|
export const http_transport = new HttpTransport(server, {
|
||||||
cors: true,
|
cors: true,
|
||||||
|
path: '/mcp',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -96,6 +96,27 @@ It will open a file with your MCP servers where you can add the following config
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## GitHub Coding Agent
|
||||||
|
|
||||||
|
- Open your repository in GitHub
|
||||||
|
- Go to Settings
|
||||||
|
- Open Copilot > Coding agent
|
||||||
|
- Edit the MCP configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"svelte": {
|
||||||
|
"type": "http",
|
||||||
|
"url": "https://mcp.svelte.dev/mcp",
|
||||||
|
"tools": ["*"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- Click _Save MCP configuration_
|
||||||
|
|
||||||
## Other clients
|
## Other clients
|
||||||
|
|
||||||
If we didn't include the MCP client you are using, refer to their documentation for `remote` servers and use `https://mcp.svelte.dev/mcp` as the URL.
|
If we didn't include the MCP client you are using, refer to their documentation for `remote` servers and use `https://mcp.svelte.dev/mcp` as the URL.
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import { beforeEach, describe, expect, it } from 'vitest';
|
||||||
|
import { server } from '../../index.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Small utility to create a JSON-RPC request without having to always specify as const
|
||||||
|
*/
|
||||||
|
function request<const T>(request: T) {
|
||||||
|
return request;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function autofixer_tool_call(code: string, is_error = false, desired_svelte_version = 5) {
|
||||||
|
const result = await server.receive({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 2,
|
||||||
|
method: 'tools/call',
|
||||||
|
params: {
|
||||||
|
name: 'svelte-autofixer',
|
||||||
|
arguments: {
|
||||||
|
code,
|
||||||
|
desired_svelte_version,
|
||||||
|
filename: 'App.svelte',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.result).toBeDefined();
|
||||||
|
if (is_error) {
|
||||||
|
return result.result;
|
||||||
|
}
|
||||||
|
expect(result.result.structuredContent).toBeDefined();
|
||||||
|
return result.result.structuredContent;
|
||||||
|
}
|
||||||
|
|
||||||
|
describe('svelte-autofixer tool', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
const initialize_request = request({
|
||||||
|
jsonrpc: '2.0',
|
||||||
|
id: 1,
|
||||||
|
method: 'initialize',
|
||||||
|
params: {
|
||||||
|
protocolVersion: '2025-06-18',
|
||||||
|
capabilities: {
|
||||||
|
roots: { listChanged: true },
|
||||||
|
},
|
||||||
|
clientInfo: {
|
||||||
|
name: 'test-client',
|
||||||
|
version: '1.0.0',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await server.receive(initialize_request, {
|
||||||
|
sessionId: 'svelte-autofixer-session',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add suggestions for js parse errors', async () => {
|
||||||
|
const content = await autofixer_tool_call(`<script>
|
||||||
|
$state count = 0;
|
||||||
|
</script>`);
|
||||||
|
expect(content.issues.length).toBeGreaterThan(0);
|
||||||
|
expect(content.suggestions).toContain(
|
||||||
|
"The code can't be compiled because a Javascript parse error. In case you are using runes like this `$state variable_name = 3;` or `$derived variable_name = 3 * count` that's not how runes are used. You need to use them as function calls without importing them: `const variable_name = $state(3)` and `const variable_name = $derived(3 * count)`.",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add suggestions for css invalid identifier', async () => {
|
||||||
|
const content = await autofixer_tool_call(`<script>
|
||||||
|
let my_color = $state('red');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.my-class {
|
||||||
|
color: {my_color};
|
||||||
|
}
|
||||||
|
</style>`);
|
||||||
|
|
||||||
|
expect(content.issues.length).toBeGreaterThan(0);
|
||||||
|
expect(content.suggestions).toContain(
|
||||||
|
"The code can't be compiled because a valid CSS identifier is expected. This sometimes means you are trying to use a variable in CSS like this: `color: {my_color}` but Svelte doesn't support that. You can use inline CSS variables for that `<div style:--color={my_color}></div>` and then use the variable as usual in CSS with `color: var(--color)`.",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should error in case the passed in version is different from 4 or 5', async () => {
|
||||||
|
const content = await autofixer_tool_call(`whatever`, true, 3);
|
||||||
|
|
||||||
|
expect(content.content).toBeDefined();
|
||||||
|
expect(content.content[0]).toBeDefined();
|
||||||
|
expect(content.content[0].text).toContain(
|
||||||
|
'The desired_svelte_version MUST be either 4 or 5 but received "3"',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -90,6 +90,10 @@ export function svelte_autofixer(server: SvelteMcp) {
|
|||||||
content.suggestions.push(
|
content.suggestions.push(
|
||||||
"The code can't be compiled because a Javascript parse error. In case you are using runes like this `$state variable_name = 3;` or `$derived variable_name = 3 * count` that's not how runes are used. You need to use them as function calls without importing them: `const variable_name = $state(3)` and `const variable_name = $derived(3 * count)`.",
|
"The code can't be compiled because a Javascript parse error. In case you are using runes like this `$state variable_name = 3;` or `$derived variable_name = 3 * count` that's not how runes are used. You need to use them as function calls without importing them: `const variable_name = $state(3)` and `const variable_name = $derived(3 * count)`.",
|
||||||
);
|
);
|
||||||
|
} else if (error.message.includes('css_expected_identifier')) {
|
||||||
|
content.suggestions.push(
|
||||||
|
"The code can't be compiled because a valid CSS identifier is expected. This sometimes means you are trying to use a variable in CSS like this: `color: {my_color}` but Svelte doesn't support that. You can use inline CSS variables for that `<div style:--color={my_color}></div>` and then use the variable as usual in CSS with `color: var(--color)`.",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
43
pnpm-lock.yaml
generated
43
pnpm-lock.yaml
generated
@@ -31,7 +31,7 @@ importers:
|
|||||||
version: 10.1.8(eslint@9.36.0(jiti@2.6.0))
|
version: 10.1.8(eslint@9.36.0(jiti@2.6.0))
|
||||||
eslint-plugin-import:
|
eslint-plugin-import:
|
||||||
specifier: ^2.32.0
|
specifier: ^2.32.0
|
||||||
version: 2.32.0(eslint@9.36.0(jiti@2.6.0))
|
version: 2.32.0(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0))
|
||||||
eslint-plugin-svelte:
|
eslint-plugin-svelte:
|
||||||
specifier: ^3.12.3
|
specifier: ^3.12.3
|
||||||
version: 3.12.4(eslint@9.36.0(jiti@2.6.0))(svelte@5.39.6)(ts-node@10.9.2(@types/node@24.5.2)(typescript@5.9.2))
|
version: 3.12.4(eslint@9.36.0(jiti@2.6.0))(svelte@5.39.6)(ts-node@10.9.2(@types/node@24.5.2)(typescript@5.9.2))
|
||||||
@@ -69,11 +69,11 @@ importers:
|
|||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
version: link:../../packages/mcp-server
|
version: link:../../packages/mcp-server
|
||||||
'@tmcp/transport-http':
|
'@tmcp/transport-http':
|
||||||
specifier: ^0.6.3
|
specifier: ^0.7.0
|
||||||
version: 0.6.3(tmcp@1.15.0(typescript@5.9.2))
|
version: 0.7.0(tmcp@1.15.1(typescript@5.9.2))
|
||||||
tmcp:
|
tmcp:
|
||||||
specifier: ^1.15.0
|
specifier: ^1.15.1
|
||||||
version: 1.15.0(typescript@5.9.2)
|
version: 1.15.1(typescript@5.9.2)
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/compat':
|
'@eslint/compat':
|
||||||
specifier: ^1.3.2
|
specifier: ^1.3.2
|
||||||
@@ -1551,10 +1551,10 @@ packages:
|
|||||||
'@tmcp/session-manager@0.1.2':
|
'@tmcp/session-manager@0.1.2':
|
||||||
resolution: {integrity: sha512-hNkEeMt7/CdD8JdjPXMlIv5OMPTp5LnBqeo1Tb/AXcm31DpgwlNbf4voJ3CeWxWAZPPZ/MgHZ682TtgGhsvXiw==}
|
resolution: {integrity: sha512-hNkEeMt7/CdD8JdjPXMlIv5OMPTp5LnBqeo1Tb/AXcm31DpgwlNbf4voJ3CeWxWAZPPZ/MgHZ682TtgGhsvXiw==}
|
||||||
|
|
||||||
'@tmcp/transport-http@0.6.3':
|
'@tmcp/transport-http@0.7.0':
|
||||||
resolution: {integrity: sha512-GBU1elN9eqRYR6aU+hvFBX+Ivq5ouspREQBtQo1Av2JOfhxozbViXvZZyeyNAx+v6iprTkblI6Qm0ai/IdHQ8g==}
|
resolution: {integrity: sha512-JvLvi2ZM3xaBIZyxy6ssGtzlhL/5JvOkjWWymxkLi84vMK44pM5zCQVN1KXAfQqHbbDlYNR/BW39cd/eP3hylA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
tmcp: ^1.14.0
|
tmcp: ^1.15.1
|
||||||
|
|
||||||
'@tmcp/transport-stdio@0.3.1':
|
'@tmcp/transport-stdio@0.3.1':
|
||||||
resolution: {integrity: sha512-r+eiHa2URw5+lBMRI0t4D84LfcWHam3DsTog/lPZSALIjlYxlFUfAaJ8dgh5gdQnmXiFJfE9hzmN0gIrB6+Lzw==}
|
resolution: {integrity: sha512-r+eiHa2URw5+lBMRI0t4D84LfcWHam3DsTog/lPZSALIjlYxlFUfAaJ8dgh5gdQnmXiFJfE9hzmN0gIrB6+Lzw==}
|
||||||
@@ -3700,6 +3700,9 @@ packages:
|
|||||||
tmcp@1.15.0:
|
tmcp@1.15.0:
|
||||||
resolution: {integrity: sha512-ell+gBSC7T5P7ogrROYsoohfLSAu0aXmKzWH8eZqkMX4K0iGc+BYJJC4kb60uJcK7PRZWBOktNGuOq1BLNFA6Q==}
|
resolution: {integrity: sha512-ell+gBSC7T5P7ogrROYsoohfLSAu0aXmKzWH8eZqkMX4K0iGc+BYJJC4kb60uJcK7PRZWBOktNGuOq1BLNFA6Q==}
|
||||||
|
|
||||||
|
tmcp@1.15.1:
|
||||||
|
resolution: {integrity: sha512-Mn2FZIcN6Vj/pJYda/Zv1t5Iv0vJIQDi+BRpcpBn9gNwID5bNtgMFOj+1LH3rkOJOTz9R78dIXSsJxDN5Vy90g==}
|
||||||
|
|
||||||
to-regex-range@5.0.1:
|
to-regex-range@5.0.1:
|
||||||
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
|
||||||
engines: {node: '>=8.0'}
|
engines: {node: '>=8.0'}
|
||||||
@@ -5287,10 +5290,11 @@ snapshots:
|
|||||||
|
|
||||||
'@tmcp/session-manager@0.1.2': {}
|
'@tmcp/session-manager@0.1.2': {}
|
||||||
|
|
||||||
'@tmcp/transport-http@0.6.3(tmcp@1.15.0(typescript@5.9.2))':
|
'@tmcp/transport-http@0.7.0(tmcp@1.15.1(typescript@5.9.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@tmcp/session-manager': 0.1.2
|
'@tmcp/session-manager': 0.1.2
|
||||||
tmcp: 1.15.0(typescript@5.9.2)
|
esm-env: 1.2.2
|
||||||
|
tmcp: 1.15.1(typescript@5.9.2)
|
||||||
|
|
||||||
'@tmcp/transport-stdio@0.3.1(tmcp@1.15.0(typescript@5.9.2))':
|
'@tmcp/transport-stdio@0.3.1(tmcp@1.15.0(typescript@5.9.2))':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -6105,16 +6109,17 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-module-utils@2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.0)):
|
eslint-module-utils@2.12.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 3.2.7
|
debug: 3.2.7
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
'@typescript-eslint/parser': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
|
||||||
eslint: 9.36.0(jiti@2.6.0)
|
eslint: 9.36.0(jiti@2.6.0)
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
eslint-plugin-import@2.32.0(eslint@9.36.0(jiti@2.6.0)):
|
eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint@9.36.0(jiti@2.6.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@rtsao/scc': 1.1.0
|
'@rtsao/scc': 1.1.0
|
||||||
array-includes: 3.1.9
|
array-includes: 3.1.9
|
||||||
@@ -6125,7 +6130,7 @@ snapshots:
|
|||||||
doctrine: 2.1.0
|
doctrine: 2.1.0
|
||||||
eslint: 9.36.0(jiti@2.6.0)
|
eslint: 9.36.0(jiti@2.6.0)
|
||||||
eslint-import-resolver-node: 0.3.9
|
eslint-import-resolver-node: 0.3.9
|
||||||
eslint-module-utils: 2.12.1(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.0))
|
eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.36.0(jiti@2.6.0))
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
is-core-module: 2.16.1
|
is-core-module: 2.16.1
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
@@ -6136,6 +6141,8 @@ snapshots:
|
|||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
string.prototype.trimend: 1.0.9
|
string.prototype.trimend: 1.0.9
|
||||||
tsconfig-paths: 3.15.0
|
tsconfig-paths: 3.15.0
|
||||||
|
optionalDependencies:
|
||||||
|
'@typescript-eslint/parser': 8.44.1(eslint@9.36.0(jiti@2.6.0))(typescript@5.9.2)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- eslint-import-resolver-typescript
|
- eslint-import-resolver-typescript
|
||||||
- eslint-import-resolver-webpack
|
- eslint-import-resolver-webpack
|
||||||
@@ -7581,6 +7588,16 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- typescript
|
- typescript
|
||||||
|
|
||||||
|
tmcp@1.15.1(typescript@5.9.2):
|
||||||
|
dependencies:
|
||||||
|
'@standard-schema/spec': 1.0.0
|
||||||
|
json-rpc-2.0: 1.7.1
|
||||||
|
sqids: 0.3.0
|
||||||
|
uri-template-matcher: 1.1.1
|
||||||
|
valibot: 1.1.0(typescript@5.9.2)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- typescript
|
||||||
|
|
||||||
to-regex-range@5.0.1:
|
to-regex-range@5.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
|
|||||||
Reference in New Issue
Block a user