Compare commits

..

11 Commits

Author SHA1 Message Date
paoloricciuti
17ed3a3e23 fix: lint 2025-10-19 11:08:57 +02:00
Paolo Ricciuti
f49bd06fbd chore: revert spacing 2025-10-19 11:05:50 +02:00
UltimateStarCoder
b98c042ae3 Correct JSON structure in remote setup documentation
Fixed JSON syntax for mcpServers configuration.
2025-10-18 17:43:58 -06:00
paoloricciuti
917a93d3fd fix: update deps and add path 2025-10-18 16:20:25 +02:00
Paolo Ricciuti
371e96befc Merge pull request #72 from adamtegen/patch-2 2025-10-17 18:58:29 +02:00
Paolo Ricciuti
bdfd5a109f fix: lint 2025-10-17 17:31:09 +02:00
Paolo Ricciuti
1c6c0a9fa7 Merge pull request #78 from sveltejs/invalid-css-autofixer
feat: suggest against js variables in css
2025-10-17 16:33:44 +02:00
paoloricciuti
a321244543 feat: suggest against js variables in css 2025-10-17 15:31:35 +02:00
paoloricciuti
ed25933466 fix: use right url + add manual triggering 2025-10-17 08:24:31 +02:00
Paolo Ricciuti
e639e3ad5c chore: apply suggestions from code review
Co-authored-by: Willow (GHOST) <ghostdevbusiness@gmail.com>
2025-10-16 16:34:25 +02:00
Adam Tegen
d0bed3e8f0 Add GitHub Coding Agent setup instructions
Added instructions for configuring GitHub Coding Agent.
2025-10-14 18:30:27 -05:00
8 changed files with 159 additions and 16 deletions

View File

@@ -0,0 +1,5 @@
---
'@sveltejs/mcp': patch
---
feat: suggest against js variables in css

View File

@@ -5,6 +5,7 @@ on:
secrets:
MCP_KEY:
required: true
workflow_dispatch:
jobs:
publish-mcp:
@@ -19,7 +20,7 @@ jobs:
env:
MCP_KEY: ${{ secrets.MCP_KEY }}
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
curl --proto '=https' --proto-redir '=https' --tlsv1.2 -fL "https://github.com/modelcontextprotocol/registry/releases/download/v1.3.3/$NAME" -O

View File

@@ -64,7 +64,7 @@
"dependencies": {
"@sveltejs/mcp-schema": "workspace:^",
"@sveltejs/mcp-server": "workspace:^",
"@tmcp/transport-http": "^0.6.3",
"tmcp": "^1.15.0"
"@tmcp/transport-http": "^0.7.0",
"tmcp": "^1.15.1"
}
}

View File

@@ -3,4 +3,5 @@ import { HttpTransport } from '@tmcp/transport-http';
export const http_transport = new HttpTransport(server, {
cors: true,
path: '/mcp',
});

View File

@@ -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
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.

View File

@@ -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"',
);
});
});

View File

@@ -90,6 +90,10 @@ export function svelte_autofixer(server: SvelteMcp) {
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)`.",
);
} 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
View File

@@ -31,7 +31,7 @@ importers:
version: 10.1.8(eslint@9.36.0(jiti@2.6.0))
eslint-plugin-import:
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:
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))
@@ -69,11 +69,11 @@ importers:
specifier: workspace:^
version: link:../../packages/mcp-server
'@tmcp/transport-http':
specifier: ^0.6.3
version: 0.6.3(tmcp@1.15.0(typescript@5.9.2))
specifier: ^0.7.0
version: 0.7.0(tmcp@1.15.1(typescript@5.9.2))
tmcp:
specifier: ^1.15.0
version: 1.15.0(typescript@5.9.2)
specifier: ^1.15.1
version: 1.15.1(typescript@5.9.2)
devDependencies:
'@eslint/compat':
specifier: ^1.3.2
@@ -1551,10 +1551,10 @@ packages:
'@tmcp/session-manager@0.1.2':
resolution: {integrity: sha512-hNkEeMt7/CdD8JdjPXMlIv5OMPTp5LnBqeo1Tb/AXcm31DpgwlNbf4voJ3CeWxWAZPPZ/MgHZ682TtgGhsvXiw==}
'@tmcp/transport-http@0.6.3':
resolution: {integrity: sha512-GBU1elN9eqRYR6aU+hvFBX+Ivq5ouspREQBtQo1Av2JOfhxozbViXvZZyeyNAx+v6iprTkblI6Qm0ai/IdHQ8g==}
'@tmcp/transport-http@0.7.0':
resolution: {integrity: sha512-JvLvi2ZM3xaBIZyxy6ssGtzlhL/5JvOkjWWymxkLi84vMK44pM5zCQVN1KXAfQqHbbDlYNR/BW39cd/eP3hylA==}
peerDependencies:
tmcp: ^1.14.0
tmcp: ^1.15.1
'@tmcp/transport-stdio@0.3.1':
resolution: {integrity: sha512-r+eiHa2URw5+lBMRI0t4D84LfcWHam3DsTog/lPZSALIjlYxlFUfAaJ8dgh5gdQnmXiFJfE9hzmN0gIrB6+Lzw==}
@@ -3700,6 +3700,9 @@ packages:
tmcp@1.15.0:
resolution: {integrity: sha512-ell+gBSC7T5P7ogrROYsoohfLSAu0aXmKzWH8eZqkMX4K0iGc+BYJJC4kb60uJcK7PRZWBOktNGuOq1BLNFA6Q==}
tmcp@1.15.1:
resolution: {integrity: sha512-Mn2FZIcN6Vj/pJYda/Zv1t5Iv0vJIQDi+BRpcpBn9gNwID5bNtgMFOj+1LH3rkOJOTz9R78dIXSsJxDN5Vy90g==}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
@@ -5287,10 +5290,11 @@ snapshots:
'@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:
'@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))':
dependencies:
@@ -6105,16 +6109,17 @@ snapshots:
transitivePeerDependencies:
- 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:
debug: 3.2.7
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-import-resolver-node: 0.3.9
transitivePeerDependencies:
- 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:
'@rtsao/scc': 1.1.0
array-includes: 3.1.9
@@ -6125,7 +6130,7 @@ snapshots:
doctrine: 2.1.0
eslint: 9.36.0(jiti@2.6.0)
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
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -6136,6 +6141,8 @@ snapshots:
semver: 6.3.1
string.prototype.trimend: 1.0.9
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:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
@@ -7581,6 +7588,16 @@ snapshots:
transitivePeerDependencies:
- 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:
dependencies:
is-number: 7.0.0