Compare commits

..

20 Commits

Author SHA1 Message Date
Rich Harris
efae225dd3 tweak 2026-05-13 13:43:07 -04:00
Rich Harris
3439fbba45 tweak 2026-05-13 13:36:12 -04:00
Rich Harris
d17023d30b tweaks 2026-05-13 13:27:44 -04:00
Rich Harris
f2c3915317 tweak 2026-05-13 13:05:39 -04:00
Rich Harris
518d3b1f3b tweak 2026-05-13 13:02:46 -04:00
Rich Harris
47f3175bb1 tweak 2026-05-13 12:57:51 -04:00
Rich Harris
b72932e4cc tweak 2026-05-13 12:39:21 -04:00
Rich Harris
c8f56e5108 house style 2026-05-13 12:36:06 -04:00
Rich Harris
b5376d2a2d flip titles 2026-05-13 12:35:51 -04:00
Rich Harris
7fbc7a2fd4 tweak 2026-05-13 12:35:12 -04:00
Paolo Ricciuti
081a99ccfe Merge branch 'main' into docs-overhaul 2026-04-29 11:34:57 +02:00
paoloricciuti
d8b20bf29c fix: move instruction up 2026-04-17 15:58:36 +02:00
paoloricciuti
c36ae53bea fix: not sure what's going on 2026-03-22 09:58:32 +01:00
paoloricciuti
dfba3a2869 fix: fix it for real 2026-03-22 09:55:57 +01:00
Paolo Ricciuti
ed3c7cf5b4 fix: update generate-subagent-docs
Co-authored-by: jyc.dev <jycouet@gmail.com>
2026-03-22 09:54:17 +01:00
paoloricciuti
46da3c6260 chore: simplify 2026-03-22 09:53:35 +01:00
Paolo Ricciuti
b486c0773f chore: apply suggestions from code review
Co-authored-by: jyc.dev <jycouet@gmail.com>
Co-authored-by: Paolo Ricciuti <ricciutipaolo@gmail.com>
Co-authored-by: Tee Ming <chewteeming01@gmail.com>
2026-03-22 09:52:51 +01:00
paoloricciuti
1e4377680b fix: remove link to opencode subagent 2026-03-21 15:58:20 +01:00
paoloricciuti
3485d45c7a fix: links in remote/local setup 2026-03-21 15:51:14 +01:00
paoloricciuti
7fef0a78fb docs: overhaul docs focus on all ai tools 2026-03-21 15:39:07 +01:00
12 changed files with 79 additions and 231 deletions

View File

@@ -0,0 +1,5 @@
---
'@sveltejs/mcp': patch
---
fix: handle non call expressions passed to `is_rune`

View File

@@ -0,0 +1,5 @@
---
'@sveltejs/mcp': patch
---
chore: remove db requirement

View File

@@ -19,8 +19,5 @@ jobs:
- name: Install dependencies
run: pnpm install
# Opencode doesn't have a build step
- name: Build Stdio
run: pnpm --filter @sveltejs/mcp run build
- run: pnpm dlx pkg-pr-new publish --compact './packages/mcp-stdio' './packages/opencode' --pnpm

View File

@@ -1,7 +1,4 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { writeFileSync, unlinkSync } from 'node:fs';
import { join } from 'node:path';
import { tmpdir } from 'node:os';
import { InMemoryTransport } from '@tmcp/transport-in-memory';
import { beforeEach, describe, expect, it } from 'vitest';
import { server } from '../../index.js';
@@ -15,18 +12,13 @@ async function autofixer_tool_call(
is_error = false,
desired_svelte_version = 5,
async = false,
ctx?: { stdio?: boolean },
) {
const result = await session.callTool(
'svelte-autofixer',
{
code,
desired_svelte_version,
filename: 'App.svelte',
async,
},
ctx,
);
const result = await session.callTool('svelte-autofixer', {
code,
desired_svelte_version,
filename: 'App.svelte',
async,
});
expect(result).toBeDefined();
if (is_error) {
@@ -154,40 +146,4 @@ describe('svelte-autofixer tool', () => {
'The desired_svelte_version MUST be either 4 or 5 but received "3"',
);
});
it('should read file content from path when stdio context is true', async () => {
const tmp_file = join(tmpdir(), `svelte-autofixer-test-${Date.now()}.svelte`);
const file_content = `<script>
$state count = 0;
</script>`;
writeFileSync(tmp_file, file_content, 'utf-8');
try {
// with stdio: true, the file is read from disk and parsed, producing issues
const content = await autofixer_tool_call(tmp_file, false, 5, false, { stdio: true });
expect(content.issues.length).toBeGreaterThan(0);
expect(content.suggestions.length).toBeGreaterThan(0);
} finally {
unlinkSync(tmp_file);
}
});
it('should treat file path as code when stdio context is not set', async () => {
const tmp_file = join(tmpdir(), `svelte-autofixer-test-${Date.now()}.svelte`);
const file_content = `<script>
$state count = 0;
</script>`;
writeFileSync(tmp_file, file_content, 'utf-8');
try {
// without stdio context, the path string is treated as raw code (plain text), no issues
const content = await autofixer_tool_call(tmp_file, false, 5, false);
expect(content.issues).toHaveLength(0);
expect(content.suggestions).toHaveLength(0);
} finally {
unlinkSync(tmp_file);
}
});
});

View File

@@ -1,47 +1,33 @@
import { basename } from 'node:path';
import { tool } from 'tmcp/utils';
import type { SvelteMcp } from '../../index.js';
import * as v from 'valibot';
import { add_autofixers_issues } from '../../autofixers/add-autofixers-issues.js';
import { add_compile_issues } from '../../autofixers/add-compile-issues.js';
import { add_eslint_issues } from '../../autofixers/add-eslint-issues.js';
import { add_autofixers_issues } from '../../autofixers/add-autofixers-issues.js';
import { icons } from '../../icons/index.js';
import { type SvelteMcp } from '../../index.js';
import { tool } from 'tmcp/utils';
let cached_schema: ReturnType<typeof get_autofixer_schema> | null = null;
function get_autofixer_schema(stdio: boolean) {
let code = v.string();
if (stdio) {
// we only add the description if we are running in stdio, this saves a few tokens for the remote server
code = v.pipe(
v.string(),
v.description(
"The code to be processed by the autofixer. It can also be a path to a file containing the code. If the file doesn't exists the string will be treated as the code",
),
);
}
return v.object({
code,
desired_svelte_version: v.pipe(
v.union([v.string(), v.number()]),
v.description(
'The desired svelte version...if possible read this from the package.json of the user project, otherwise use some hint from the wording (if the user asks for runes it wants version 5). Default to 5 in case of doubt.',
),
const autofixer_schema = v.object({
code: v.string(),
desired_svelte_version: v.pipe(
v.union([v.string(), v.number()]),
v.description(
'The desired svelte version...if possible read this from the package.json of the user project, otherwise use some hint from the wording (if the user asks for runes it wants version 5). Default to 5 in case of doubt.',
),
async: v.pipe(
v.optional(v.boolean()),
v.description(
'If true the code is an async component/module and might use await in the markup or top-level awaits in the script tag. If possible check the svelte.config.js/svelte.config.ts to check if the option is enabled otherwise asks the user if they prefer using it or not. You can only use this option if the version is 5.',
),
),
async: v.pipe(
v.optional(v.boolean()),
v.description(
'If true the code is an async component/module and might use await in the markup or top-level awaits in the script tag. If possible check the svelte.config.js/svelte.config.ts to check if the option is enabled otherwise asks the user if they prefer using it or not. You can only use this option if the version is 5.',
),
filename: v.pipe(
v.optional(v.string()),
v.description(
'The filename of the component if available, it MUST be only the Component name with .svelte or .svelte.ts extension and not the entire path.',
),
),
filename: v.pipe(
v.optional(v.string()),
v.description(
'The filename of the component if available, it MUST be only the Component name with .svelte or .svelte.ts extension and not the entire path.',
),
});
}
),
});
const autofixer_output_schema = v.object({
issues: v.array(v.string()),
@@ -54,7 +40,7 @@ export async function svelte_autofixer_handler({
desired_svelte_version: desired_svelte_version_unchecked,
async,
filename: filename_or_path,
}: v.InferInput<ReturnType<typeof get_autofixer_schema>>) {
}: v.InferInput<typeof autofixer_schema>) {
// we validate manually because some clients don't support union in the input schema (looking at you cursor)
const parsed_version = v.safeParse(
v.union([v.literal(4), v.literal(5), v.literal('4'), v.literal('5')]),
@@ -124,11 +110,7 @@ export function svelte_autofixer(server: SvelteMcp) {
title: 'Svelte Autofixer',
description:
'Given a svelte component or module returns a list of suggestions to fix any issues it has. This tool MUST be used whenever the user is asking to write svelte code before sending the code back to the user',
get schema() {
return (
cached_schema ?? (cached_schema = get_autofixer_schema(server.ctx.custom?.stdio ?? false))
);
},
schema: autofixer_schema,
outputSchema: autofixer_output_schema,
annotations: {
title: 'Svelte Autofixer',
@@ -147,18 +129,6 @@ export function svelte_autofixer(server: SvelteMcp) {
if (server.ctx.sessionId && server.ctx.custom?.track) {
await server.ctx.custom?.track?.(server.ctx.sessionId, 'svelte-autofixer');
}
// we only do this if we know we are running in stdio mode (only stdio pass the context as true)
if (server.ctx.custom?.stdio) {
const [exists_sync, read_file] = await Promise.all([
import('node:fs').then((mod) => mod.existsSync),
import('node:fs/promises').then((mod) => mod.readFile),
]);
if (exists_sync(code)) {
code = await read_file(code, 'utf-8');
}
}
try {
const content = await svelte_autofixer_handler({
code,

View File

@@ -24,7 +24,6 @@ export const server = new McpServer(
},
).withContext<{
track?: (sessionId: string, event: string, extra?: string) => Promise<void>;
stdio?: boolean;
}>();
export type SvelteMcp = typeof server;

View File

@@ -1,15 +1,5 @@
# @sveltejs/mcp
## 0.1.23
### Patch Changes
- feat: allow stdio mcp to read the content of the file directly ([#198](https://github.com/sveltejs/ai-tools/pull/198))
- fix: handle non call expressions passed to `is_rune` ([#201](https://github.com/sveltejs/ai-tools/pull/201))
- chore: remove db requirement ([#196](https://github.com/sveltejs/ai-tools/pull/196))
## 0.1.22
### Patch Changes

View File

@@ -1,6 +1,6 @@
{
"name": "@sveltejs/mcp",
"version": "0.1.23",
"version": "0.1.22",
"type": "module",
"license": "MIT",
"mcpName": "dev.svelte/mcp",

View File

@@ -9,7 +9,7 @@
"subfolder": "packages/mcp-stdio",
"source": "github"
},
"version": "0.1.23",
"version": "0.1.22",
"websiteUrl": "https://svelte.dev/docs/mcp/overview",
"icons": [
{
@@ -25,7 +25,7 @@
{
"registryType": "npm",
"identifier": "@sveltejs/mcp",
"version": "0.1.23",
"version": "0.1.22",
"runtimeHint": "npx",
"transport": {
"type": "stdio"

View File

@@ -14,9 +14,7 @@ const cli = sade('svelte-mcp');
cli.command('__mcp', '', { default: true }).action(() => {
const transport = new StdioTransport(server);
transport.listen({
stdio: true,
});
transport.listen();
});
cli

134
pnpm-lock.yaml generated
View File

@@ -6,18 +6,9 @@ settings:
catalogs:
ai:
'@anthropic-ai/sdk':
specifier: ^0.71.0
version: 0.71.2
'@mcp-ui/server':
specifier: ^6.0.0
version: 6.0.0
'@modelcontextprotocol/inspector':
specifier: ^0.19.0
version: 0.19.0
'@opencode-ai/plugin':
specifier: ^1.1.44
version: 1.1.44
lint:
'@eslint/compat':
specifier: ^2.0.0
@@ -25,27 +16,12 @@ catalogs:
'@eslint/js':
specifier: ^9.36.0
version: 9.39.2
'@types/eslint-scope':
specifier: ^8.3.2
version: 8.4.0
'@typescript-eslint/parser':
specifier: ^8.44.0
version: 8.54.0
'@typescript-eslint/types':
specifier: ^8.44.0
version: 8.54.0
eslint:
specifier: ^9.36.0
version: 9.39.2
eslint-config-prettier:
specifier: ^10.0.1
version: 10.1.8
eslint-plugin-import:
specifier: ^2.32.0
version: 2.32.0
eslint-plugin-pnpm:
specifier: ^1.3.0
version: 1.5.0
eslint-plugin-svelte:
specifier: ^3.12.5
version: 3.14.0
@@ -61,9 +37,6 @@ catalogs:
svelte-eslint-parser:
specifier: ^1.4.0
version: 1.4.1
typescript-eslint:
specifier: ^8.44.0
version: 8.54.0
svelte:
'@sveltejs/adapter-vercel':
specifier: ^6.0.0
@@ -81,64 +54,22 @@ catalogs:
specifier: ^4.0.0
version: 4.3.5
tmcp:
'@tmcp/adapter-valibot':
specifier: ^0.1.5
version: 0.1.5
'@tmcp/transport-http':
specifier: ^0.8.5
version: 0.8.5
'@tmcp/transport-in-memory':
specifier: ^0.0.6
version: 0.0.6
'@tmcp/transport-stdio':
specifier: ^0.4.2
version: 0.4.2
specifier: ^0.8.4
version: 0.8.4
tmcp:
specifier: ^1.19.3
version: 1.19.3
specifier: ^1.19.0
version: 1.19.2
tooling:
'@changesets/cli':
specifier: ^2.29.7
version: 2.29.8
'@svitejs/changesets-changelog-github-compact':
specifier: ^1.2.0
version: 1.2.0
'@types/estree':
specifier: ^1.0.8
version: 1.0.8
'@types/node':
specifier: ^24.3.1
version: 24.10.9
'@valibot/to-json-schema':
specifier: ^1.5.0
version: 1.5.0
'@vercel/analytics':
specifier: ^2.0.0
version: 2.0.1
dotenv:
specifier: ^17.2.3
version: 17.2.3
node-resolve-ts:
specifier: ^1.0.2
version: 1.0.2
publint:
specifier: ^0.3.13
version: 0.3.17
sade:
specifier: 1.8.1
version: 1.8.1
ts-blank-space:
specifier: ^0.7.0
version: 0.7.0
tsdown:
specifier: ^0.20.0
version: 0.20.1
typescript:
specifier: ^5.0.0
version: 5.9.3
valibot:
specifier: ^1.2.0
version: 1.2.0
vite:
specifier: ^7.0.4
version: 7.3.1
@@ -148,9 +79,6 @@ catalogs:
vitest:
specifier: ^4.0.0
version: 4.0.18
zimmerframe:
specifier: ^1.1.4
version: 1.1.4
importers:
@@ -221,13 +149,13 @@ importers:
version: link:../../packages/mcp-server
'@tmcp/transport-http':
specifier: catalog:tmcp
version: 0.8.5(tmcp@1.19.3(typescript@5.9.3))
version: 0.8.4(tmcp@1.19.2(typescript@5.9.3))
'@vercel/analytics':
specifier: catalog:tooling
version: 2.0.1(@sveltejs/kit@2.50.1(@sveltejs/vite-plugin-svelte@6.2.4(svelte@5.48.4)(vite@7.3.1(@types/node@24.10.9)(yaml@2.8.2)))(svelte@5.48.4)(typescript@5.9.3)(vite@7.3.1(@types/node@24.10.9)(yaml@2.8.2)))(react@18.3.1)(svelte@5.48.4)
tmcp:
specifier: catalog:tmcp
version: 1.19.3(typescript@5.9.3)
version: 1.19.2(typescript@5.9.3)
devDependencies:
'@eslint/compat':
specifier: catalog:lint
@@ -297,10 +225,10 @@ importers:
version: 6.0.0(hono@4.11.7)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(zod@4.1.8)
'@tmcp/adapter-valibot':
specifier: catalog:tmcp
version: 0.1.5(tmcp@1.19.3(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3))
version: 0.1.5(tmcp@1.19.2(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3))
'@tmcp/transport-in-memory':
specifier: catalog:tmcp
version: 0.0.6(tmcp@1.19.3(typescript@5.9.3))
version: 0.0.5(tmcp@1.19.2(typescript@5.9.3))
'@typescript-eslint/parser':
specifier: catalog:lint
version: 8.54.0(eslint@9.39.2)(typescript@5.9.3)
@@ -318,7 +246,7 @@ importers:
version: 1.4.1(svelte@5.48.4)
tmcp:
specifier: catalog:tmcp
version: 1.19.3(typescript@5.9.3)
version: 1.19.2(typescript@5.9.3)
ts-blank-space:
specifier: catalog:tooling
version: 0.7.0
@@ -364,14 +292,14 @@ importers:
version: 1.8.1
tmcp:
specifier: catalog:tmcp
version: 1.19.3(typescript@5.9.3)
version: 1.19.2(typescript@5.9.3)
devDependencies:
'@sveltejs/mcp-server':
specifier: workspace:^
version: link:../mcp-server
'@tmcp/transport-stdio':
specifier: catalog:tmcp
version: 0.4.2(tmcp@1.19.3(typescript@5.9.3))
version: 0.4.1(tmcp@1.19.2(typescript@5.9.3))
'@types/node':
specifier: catalog:tooling
version: 24.10.9
@@ -1797,8 +1725,8 @@ packages:
peerDependencies:
tmcp: ^1.16.3
'@tmcp/transport-http@0.8.5':
resolution: {integrity: sha512-qQLqiCTtbxtTSswqOn/782df7O57RxI/yLUtCDQ++kHEhbmDUc8glmmtGJ3mrb7yPSPoM5VF2Pc2Q5cA6quzLA==}
'@tmcp/transport-http@0.8.4':
resolution: {integrity: sha512-n/4oIYjHyX5i6LFC3+qlxtc/IIv1xoqLhPVbdA5VYDyUWU6QRBU3+ffMXQuAPs0Q6Z+ZCzcO30V90yRMAxuriQ==}
peerDependencies:
'@tmcp/auth': ^0.3.3 || ^0.4.0
tmcp: ^1.18.0
@@ -1806,13 +1734,13 @@ packages:
'@tmcp/auth':
optional: true
'@tmcp/transport-in-memory@0.0.6':
resolution: {integrity: sha512-j+xcfQa7ksiIkA/8s3SAsTnM3GeZTd+X8F++Mv/tAT91+UkCzyhemPz0MqW7i1ruxJyIWooOB6JhWCsyF+LvhA==}
'@tmcp/transport-in-memory@0.0.5':
resolution: {integrity: sha512-m8l4+GdCj3NNwVxClnE8fV0yVn5ihpXhIsoOTG3CxeKoC/4H5+HPXeIIb25uSfFt6rccDfqH7DDPjMGDfPtoXA==}
peerDependencies:
tmcp: ^1.17.0
'@tmcp/transport-stdio@0.4.2':
resolution: {integrity: sha512-OLVLJzUXAKsCvenkjPf5ygli9ZcbEv3Lcei/ry+DB4T1NzvDc1oU3m41zYtHhAmbES1h6om3T9f/zonBSDFMRQ==}
'@tmcp/transport-stdio@0.4.1':
resolution: {integrity: sha512-464x8HNrvjLLtKZsrFWUL13GnBFFtrNoWxnE0rHbcmQSYRqtS8WseWtQCYstj2Vcg9kRlIUVFGDIljGNP4/N4A==}
peerDependencies:
tmcp: ^1.16.3
@@ -3829,8 +3757,8 @@ packages:
resolution: {integrity: sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==}
engines: {node: '>=14.0.0'}
tmcp@1.19.3:
resolution: {integrity: sha512-plz/TLKNFrdfQN32LjCTN6ULy6pynfGPgHcU7KGCI5dBrxQ9Mub99SmcYuzxEkLjJooQuOD3gosSwZEl1htOtw==}
tmcp@1.19.2:
resolution: {integrity: sha512-/AEG/jlzflGKqCKm7GNdhz50VtFlN+3vcnKd+iQJXcHdIPrpCRMolEj57SfgcXcfE2ouX7J6Q05gPKsS2NZhKg==}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
@@ -5482,31 +5410,31 @@ snapshots:
transitivePeerDependencies:
- encoding
'@tmcp/adapter-valibot@0.1.5(tmcp@1.19.3(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3))':
'@tmcp/adapter-valibot@0.1.5(tmcp@1.19.2(typescript@5.9.3))(valibot@1.2.0(typescript@5.9.3))':
dependencies:
'@standard-schema/spec': 1.1.0
'@valibot/to-json-schema': 1.5.0(valibot@1.2.0(typescript@5.9.3))
tmcp: 1.19.3(typescript@5.9.3)
tmcp: 1.19.2(typescript@5.9.3)
valibot: 1.2.0(typescript@5.9.3)
'@tmcp/session-manager@0.2.1(tmcp@1.19.3(typescript@5.9.3))':
'@tmcp/session-manager@0.2.1(tmcp@1.19.2(typescript@5.9.3))':
dependencies:
tmcp: 1.19.3(typescript@5.9.3)
tmcp: 1.19.2(typescript@5.9.3)
'@tmcp/transport-http@0.8.5(tmcp@1.19.3(typescript@5.9.3))':
'@tmcp/transport-http@0.8.4(tmcp@1.19.2(typescript@5.9.3))':
dependencies:
'@tmcp/session-manager': 0.2.1(tmcp@1.19.3(typescript@5.9.3))
'@tmcp/session-manager': 0.2.1(tmcp@1.19.2(typescript@5.9.3))
esm-env: 1.2.2
tmcp: 1.19.3(typescript@5.9.3)
tmcp: 1.19.2(typescript@5.9.3)
'@tmcp/transport-in-memory@0.0.6(tmcp@1.19.3(typescript@5.9.3))':
'@tmcp/transport-in-memory@0.0.5(tmcp@1.19.2(typescript@5.9.3))':
dependencies:
json-rpc-2.0: 1.7.1
tmcp: 1.19.3(typescript@5.9.3)
tmcp: 1.19.2(typescript@5.9.3)
'@tmcp/transport-stdio@0.4.2(tmcp@1.19.3(typescript@5.9.3))':
'@tmcp/transport-stdio@0.4.1(tmcp@1.19.2(typescript@5.9.3))':
dependencies:
tmcp: 1.19.3(typescript@5.9.3)
tmcp: 1.19.2(typescript@5.9.3)
'@tsconfig/node10@1.0.12': {}
@@ -7697,7 +7625,7 @@ snapshots:
tinyrainbow@3.0.3: {}
tmcp@1.19.3(typescript@5.9.3):
tmcp@1.19.2(typescript@5.9.3):
dependencies:
'@standard-schema/spec': 1.1.0
json-rpc-2.0: 1.7.1

View File

@@ -31,11 +31,11 @@ catalogs:
svelte: ^5.47.0
svelte-check: ^4.0.0
tmcp:
'@tmcp/adapter-valibot': ^0.1.5
'@tmcp/transport-http': ^0.8.5
'@tmcp/transport-in-memory': ^0.0.6
'@tmcp/transport-stdio': ^0.4.2
tmcp: ^1.19.3
'@tmcp/adapter-valibot': ^0.1.4
'@tmcp/transport-http': ^0.8.4
'@tmcp/transport-in-memory': ^0.0.5
'@tmcp/transport-stdio': ^0.4.0
tmcp: ^1.19.0
tooling:
'@changesets/cli': ^2.29.7
'@svitejs/changesets-changelog-github-compact': ^1.2.0