mirror of
https://github.com/sveltejs/ai-tools.git
synced 2026-07-04 03:19:38 +08:00
Compare commits
23 Commits
remove-db-
...
docs-overh
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efae225dd3 | ||
|
|
3439fbba45 | ||
|
|
d17023d30b | ||
|
|
f2c3915317 | ||
|
|
518d3b1f3b | ||
|
|
47f3175bb1 | ||
|
|
b72932e4cc | ||
|
|
c8f56e5108 | ||
|
|
b5376d2a2d | ||
|
|
7fbc7a2fd4 | ||
|
|
081a99ccfe | ||
|
|
841af5b3a4 | ||
|
|
1ce957ac72 | ||
|
|
e429cd7839 | ||
|
|
d8b20bf29c | ||
|
|
c36ae53bea | ||
|
|
dfba3a2869 | ||
|
|
ed3c7cf5b4 | ||
|
|
46da3c6260 | ||
|
|
b486c0773f | ||
|
|
1e4377680b | ||
|
|
3485d45c7a | ||
|
|
7fef0a78fb |
5
.changeset/salty-jokes-crash.md
Normal file
5
.changeset/salty-jokes-crash.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@sveltejs/mcp': patch
|
||||
---
|
||||
|
||||
fix: handle non call expressions passed to `is_rune`
|
||||
5
.changeset/small-actors-notice.md
Normal file
5
.changeset/small-actors-notice.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@sveltejs/mcp': patch
|
||||
---
|
||||
|
||||
chore: remove db requirement
|
||||
2
.github/workflows/check.yml
vendored
2
.github/workflows/check.yml
vendored
@@ -32,6 +32,4 @@ jobs:
|
||||
- name: Run type check
|
||||
run: pnpm run check
|
||||
env:
|
||||
DATABASE_URL: file:test.db
|
||||
DATABASE_TOKEN: dummy-key
|
||||
VOYAGE_API_KEY: dummy-key
|
||||
|
||||
2
.github/workflows/lint.yml
vendored
2
.github/workflows/lint.yml
vendored
@@ -32,6 +32,4 @@ jobs:
|
||||
- name: Run linting
|
||||
run: pnpm run lint
|
||||
env:
|
||||
DATABASE_URL: file:test.db
|
||||
VOYAGE_API_KEY: dummy-key
|
||||
DATABASE_TOKEN: dummy-key
|
||||
|
||||
3
.github/workflows/sync-plugins.yml
vendored
3
.github/workflows/sync-plugins.yml
vendored
@@ -52,6 +52,9 @@ jobs:
|
||||
- name: Generate skills documentation
|
||||
run: pnpm generate-skill-docs
|
||||
|
||||
- name: Generate subagent documentation
|
||||
run: pnpm generate-subagent-docs
|
||||
|
||||
- name: Check for changes
|
||||
id: git-check
|
||||
run: |
|
||||
|
||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -32,13 +32,9 @@ jobs:
|
||||
- name: Build project
|
||||
run: pnpm run build
|
||||
env:
|
||||
DATABASE_URL: file:test.db
|
||||
VOYAGE_API_KEY: dummy-key
|
||||
DATABASE_TOKEN: dummy-key
|
||||
|
||||
- name: Run tests
|
||||
run: pnpm run test
|
||||
env:
|
||||
DATABASE_URL: file:test.db
|
||||
VOYAGE_API_KEY: dummy-key
|
||||
DATABASE_TOKEN: dummy-key
|
||||
|
||||
@@ -83,7 +83,6 @@ Located in `src/lib/server/analyze/`:
|
||||
|
||||
Required environment variables:
|
||||
|
||||
- `DATABASE_URL`: SQLite database path (default: `file:test.db`)
|
||||
- `VOYAGE_API_KEY`: API key for embeddings support (optional)
|
||||
|
||||
When connected to the svelte-llm MCP server, you have access to comprehensive Svelte 5 and SvelteKit documentation. Here's how to use the available tools effectively:
|
||||
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2026 [Svelte Contributors](https://github.com/sveltejs/ai-tools/graphs/contributors)
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -1,3 +1 @@
|
||||
DATABASE_URL=file:test.db
|
||||
DATABASE_TOKEN=needs_to_be_set_but_it_can_be_anything
|
||||
VOYAGE_API_KEY=your_actual_api_key_here
|
||||
@@ -1,12 +0,0 @@
|
||||
import { defineConfig } from 'drizzle-kit';
|
||||
|
||||
if (!process.env.DATABASE_URL) throw new Error('DATABASE_URL is not set');
|
||||
if (!process.env.DATABASE_TOKEN) throw new Error('DATABASE_TOKEN is not set');
|
||||
|
||||
export default defineConfig({
|
||||
schema: './src/lib/server/db/schema.ts',
|
||||
dialect: 'turso',
|
||||
dbCredentials: { url: process.env.DATABASE_URL, authToken: process.env.DATABASE_TOKEN },
|
||||
verbose: true,
|
||||
strict: true,
|
||||
});
|
||||
@@ -23,10 +23,6 @@
|
||||
"test:unit": "vitest",
|
||||
"test": "npm run test:unit -- --run",
|
||||
"test:watch": "npm run test:unit -- --watch",
|
||||
"db:push": "drizzle-kit push",
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:studio": "drizzle-kit studio",
|
||||
"inspect": "pnpm mcp-inspector"
|
||||
},
|
||||
"keywords": [
|
||||
@@ -39,15 +35,12 @@
|
||||
"devDependencies": {
|
||||
"@eslint/compat": "catalog:lint",
|
||||
"@eslint/js": "catalog:lint",
|
||||
"@libsql/client": "catalog:orm",
|
||||
"@modelcontextprotocol/inspector": "catalog:ai",
|
||||
"@sveltejs/adapter-vercel": "catalog:svelte",
|
||||
"@sveltejs/kit": "catalog:svelte",
|
||||
"@sveltejs/vite-plugin-svelte": "catalog:svelte",
|
||||
"@types/node": "catalog:tooling",
|
||||
"@typescript-eslint/parser": "catalog:lint",
|
||||
"drizzle-kit": "catalog:orm",
|
||||
"drizzle-orm": "catalog:orm",
|
||||
"eslint-config-prettier": "catalog:lint",
|
||||
"eslint-plugin-svelte": "catalog:lint",
|
||||
"globals": "catalog:lint",
|
||||
@@ -62,7 +55,6 @@
|
||||
"vitest": "catalog:tooling"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sveltejs/mcp-schema": "workspace:^",
|
||||
"@sveltejs/mcp-server": "workspace:^",
|
||||
"@tmcp/transport-http": "catalog:tmcp",
|
||||
"@vercel/analytics": "catalog:tooling",
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { dev } from '$app/environment';
|
||||
import { http_transport } from '$lib/mcp/index.js';
|
||||
import { db } from '$lib/server/db/index.js';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { track } from '@vercel/analytics/server';
|
||||
|
||||
@@ -17,7 +16,6 @@ export async function handle({ event, resolve }) {
|
||||
}
|
||||
}
|
||||
const mcp_response = await http_transport.respond(event.request, {
|
||||
db,
|
||||
// only add analytics in production
|
||||
track: dev
|
||||
? undefined
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { createClient } from '@libsql/client';
|
||||
import { drizzle } from 'drizzle-orm/libsql';
|
||||
import * as schema from './schema.js';
|
||||
import { DATABASE_TOKEN, DATABASE_URL } from '$env/static/private';
|
||||
if (!DATABASE_URL) throw new Error('DATABASE_URL is not set');
|
||||
if (!DATABASE_TOKEN) throw new Error('DATABASE_TOKEN is not set');
|
||||
|
||||
const client = createClient({
|
||||
url: DATABASE_URL,
|
||||
authToken: DATABASE_TOKEN,
|
||||
});
|
||||
|
||||
export const db = drizzle(client, { schema, logger: true });
|
||||
@@ -1,2 +0,0 @@
|
||||
// we need to re-export from here to allow for the drizzle config to pick them up for migrations
|
||||
export * from '@sveltejs/mcp-schema/schema';
|
||||
@@ -2,25 +2,11 @@
|
||||
title: Overview
|
||||
---
|
||||
|
||||
The Svelte MCP ([Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro)) server can help your LLM or agent of choice write better Svelte code. It works by providing documentation relevant to the task at hand, and statically analysing generated code so that it can suggest fixes and best practices.
|
||||
The following pages will help you set up and use the AI tools officially maintained by the Svelte team.
|
||||
|
||||
## Setup
|
||||
There are four tools, designed to help your agent write correct, robust Svelte code. They are designed to work together, but each can be used individually:
|
||||
|
||||
The setup varies based on the version of the MCP you prefer — remote or local — and your chosen MCP client (e.g. Claude Code, Codex CLI or GitHub Copilot):
|
||||
|
||||
- [local setup](local-setup) using `@sveltejs/mcp`
|
||||
- [remote setup](remote-setup) using `https://mcp.svelte.dev/mcp`
|
||||
|
||||
## Usage
|
||||
|
||||
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. Or [`GEMINI.md`](https://geminicli.com/docs/cli/gemini-md/), if using GEMINI). This will tell the LLM which tools are available and when it's appropriate to use them.
|
||||
|
||||
> [!NOTE] This is already setup for you when using `npx sv add mcp`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
````markdown
|
||||
@include .generated/agents.md
|
||||
````
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
If your MCP client supports it, we also recommend using the [svelte-task](prompts#svelte-task) prompt to instruct the LLM on the best way to use the MCP server.
|
||||
- [Instructions](instructions): small prompt always injected into your session to make your agent more aware of the available tools
|
||||
- [MCP Server](mcp): with tools, prompts and resources to give your agent more context, by pulling directly from the official Svelte documentation and using static analysis to correct common generative AI pitfalls
|
||||
- [Skills](skills): lazy-loaded descriptions that teach your agent Svelte best practices, and how to use the [`@sveltejs/mcp` cli](cli)
|
||||
- [Subagents](subagent): focused agents that can be invoked in parallel to execute atomic operations in a separate context window
|
||||
|
||||
13
documentation/docs/20-instructions/10-instructions.md
Normal file
13
documentation/docs/20-instructions/10-instructions.md
Normal file
@@ -0,0 +1,13 @@
|
||||
---
|
||||
title: AGENTS.md
|
||||
---
|
||||
|
||||
To get the most out of the [MCP server](mcp) and [skills](skills) 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) or [`GEMINI.md`](https://geminicli.com/docs/cli/gemini-md/), if using Claude Code or Gemini). This will tell your agent which tools are available and when it is appropriate to use them.
|
||||
|
||||
> [!NOTE] This is already setup for you when using `npx sv add mcp`
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
````markdown
|
||||
@include .generated/agents.md
|
||||
````
|
||||
<!-- prettier-ignore-end -->
|
||||
3
documentation/docs/20-instructions/index.md
Normal file
3
documentation/docs/20-instructions/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: Instructions
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: Setup
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: Capabilities
|
||||
---
|
||||
16
documentation/docs/30-mcp/10-mcp.md
Normal file
16
documentation/docs/30-mcp/10-mcp.md
Normal file
@@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
The Svelte MCP ([Model Context Protocol](https://modelcontextprotocol.io/docs/getting-started/intro)) server can help your agent write better Svelte code. It works by providing relevant documentation, and statically analysing generated code so that it can suggest fixes and best practices.
|
||||
|
||||
## Setup
|
||||
|
||||
The setup varies based on the version of the MCP you prefer — remote or local — and your chosen MCP client (e.g. Claude Code, Codex CLI or GitHub Copilot):
|
||||
|
||||
- [local setup](local-setup) using `@sveltejs/mcp`
|
||||
- [remote setup](remote-setup) using `https://mcp.svelte.dev/mcp`
|
||||
|
||||
## Usage
|
||||
|
||||
If your MCP client supports it, we also recommend using the [svelte-task](prompts#svelte-task) prompt to instruct the LLM on the best way to use the MCP server.
|
||||
@@ -112,6 +112,8 @@ opencode mcp add
|
||||
|
||||
## Cursor
|
||||
|
||||
You can automatically configure the MCP server using the [Cursor plugin](cursor-plugin) (recommended). If you prefer to configure the MCP server manually you can:
|
||||
|
||||
- Open the command palette
|
||||
- Select "View: Open MCP Settings"
|
||||
- Click on "Add custom MCP"
|
||||
@@ -16,7 +16,7 @@ claude mcp add -t http -s [scope] svelte https://mcp.svelte.dev/mcp
|
||||
|
||||
You can choose your preferred `scope` (it must be `user`, `project` or `local`) and `name`.
|
||||
|
||||
If you prefer you can also install the `svelte` plugin in [the Svelte Claude Code Marketplace](plugin) that will give you both the remote server and useful [skills](skills).
|
||||
If you prefer you can also install the `svelte` plugin in [the Svelte Claude Code Marketplace](claude-plugin) that will give you both the remote server and useful [skills](skills).
|
||||
|
||||
## Claude Desktop
|
||||
|
||||
@@ -102,6 +102,8 @@ opencode mcp add
|
||||
|
||||
## Cursor
|
||||
|
||||
You can automatically configure the MCP server using the [Cursor plugin](cursor-plugin) (recommended). If you prefer to configure the MCP server manually you can:
|
||||
|
||||
- Open the command palette
|
||||
- Select "View: Open MCP Settings"
|
||||
- Click on "Add custom MCP"
|
||||
78
documentation/docs/30-mcp/70-cli.md
Normal file
78
documentation/docs/30-mcp/70-cli.md
Normal file
@@ -0,0 +1,78 @@
|
||||
---
|
||||
title: CLI
|
||||
---
|
||||
|
||||
The `@sveltejs/mcp` npm package normally launches the local `stdio` MCP server:
|
||||
|
||||
```bash
|
||||
npx -y @sveltejs/mcp
|
||||
```
|
||||
|
||||
If you invoke it with a subcommand, it behaves like a regular CLI and prints the result directly in your terminal instead. This is useful for agents, scripts and quick manual checks.
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
npx -y @sveltejs/mcp <command> [options]
|
||||
```
|
||||
|
||||
Available commands:
|
||||
|
||||
- `list-sections`
|
||||
- `get-documentation <sections>`
|
||||
- `svelte-autofixer <code_or_path>`
|
||||
|
||||
You can learn more about the commands with
|
||||
|
||||
```bash
|
||||
npx -y @sveltejs/mcp --help
|
||||
npx -y @sveltejs/mcp <command> --help
|
||||
npx -y @sveltejs/mcp --version
|
||||
```
|
||||
|
||||
## `list-sections`
|
||||
|
||||
Lists all available Svelte and SvelteKit documentation sections.
|
||||
|
||||
```bash
|
||||
npx -y @sveltejs/mcp list-sections
|
||||
```
|
||||
|
||||
The output is a structured text list of sections, including each section's title, `use_cases`, and documentation path. This is the same catalog the MCP tool uses before calling `get-documentation`.
|
||||
|
||||
## `get-documentation`
|
||||
|
||||
Fetches the full documentation for one or more sections.
|
||||
|
||||
```bash
|
||||
npx -y @sveltejs/mcp get-documentation 'svelte/$state'
|
||||
# or
|
||||
npx -y @sveltejs/mcp get-documentation 'svelte/$state,svelte/await-expressions'
|
||||
```
|
||||
|
||||
Each section can be matched by title or by documentation path. If a section cannot be found, the CLI returns an error plus similar matches when available.
|
||||
|
||||
## `svelte-autofixer`
|
||||
|
||||
Runs the Svelte autofixer against either inline code or a file path:
|
||||
|
||||
```bash
|
||||
npx -y @sveltejs/mcp svelte-autofixer 'src/routes/+page.svelte'
|
||||
```
|
||||
|
||||
If the argument is an existing path, the CLI reads the file automatically. Otherwise it treats the argument as raw Svelte code.
|
||||
|
||||
Because most shells expand `$`, inline code should be quoted or escaped correctly. In practice, passing a file path is usually easier than passing source directly.
|
||||
|
||||
Available options:
|
||||
|
||||
- `--svelte-version <4|5>` - choose which Svelte version to validate against (defaults to `5`)
|
||||
- `--async` - enable async Svelte analysis for Svelte 5 projects
|
||||
|
||||
The command prints an object with:
|
||||
|
||||
- `issues`
|
||||
- `suggestions`
|
||||
- `require_another_tool_call_after_fixing`
|
||||
|
||||
This makes it easy to use in an agentic loop: run the autofixer, apply fixes, then run it again until it reports no remaining issues or suggestions.
|
||||
3
documentation/docs/30-mcp/index.md
Normal file
3
documentation/docs/30-mcp/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: MCP server
|
||||
---
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: Claude Code Plugin
|
||||
---
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Subagent
|
||||
---
|
||||
|
||||
The Svelte plugin includes a specialized subagent called `svelte-file-editor` designed for creating, editing, and reviewing Svelte files.
|
||||
|
||||
## Benefits
|
||||
|
||||
The subagent has access to its own context window, allowing it to fetch the documentation, iterate with the `svelte-autofixer` tool and write to the file system without wasting context in the main agent.
|
||||
|
||||
The delegation should happen automatically when appropriate, but you can also explicitly request the subagent be used for Svelte-related tasks.
|
||||
@@ -4,8 +4,8 @@ title: Overview
|
||||
|
||||
This is the list of available skills provided by the Svelte MCP package. Skills are sets of instructions that AI agents can load on-demand to help with specific tasks.
|
||||
|
||||
Skills are available in both the Claude Code plugin (installed via the marketplace) and the OpenCode plugin (`@sveltejs/opencode`). They can also be manually installed in your `.claude/skills/` or `.opencode/skills/` folder.
|
||||
Skills are available in both the Claude Code plugin (installed via the marketplace) and the OpenCode plugin (`@sveltejs/opencode`). They can also be manually installed in your `.claude/skills` or `.opencode/skills` folder.
|
||||
|
||||
You can download the latest skills from the [releases page](https://github.com/sveltejs/ai-tools/releases) or find them in the [`plugins/svelte/skills`](https://github.com/sveltejs/ai-tools/tree/main/plugins/svelte/skills) folder.
|
||||
You can download the latest skills from the [releases page](https://github.com/sveltejs/ai-tools/releases) of the repo, or find them in the [`plugins/svelte/skills`](https://github.com/sveltejs/ai-tools/tree/main/plugins/svelte/skills) folder.
|
||||
|
||||
@include .generated/skills.md
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: OpenCode Plugin
|
||||
---
|
||||
@@ -1,53 +0,0 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
OpenCode has a [plugin system](https://opencode.ai/docs/plugins/) that allows developers to add MCP servers, agents and commands programmatically. Svelte has an OpenCode plugin published under `@sveltejs/opencode`.
|
||||
|
||||
## Installation
|
||||
|
||||
To install the plugin in OpenCode you can edit your [OpenCode config](https://opencode.ai/docs/config/) (either the global or the local one), adding `@sveltejs/opencode` to the list of plugins.
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"plugin": ["@sveltejs/opencode"]
|
||||
}
|
||||
```
|
||||
|
||||
That's it! You now have the Svelte MCP server, [skills](skills), and the [file editor subagent](opencode-subagent) configured for you.
|
||||
|
||||
## Configuration
|
||||
|
||||
The default configuration for the Svelte OpenCode plugin looks like this...
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://svelte.dev/opencode/schema.json",
|
||||
"mcp": {
|
||||
"type": "remote",
|
||||
"enabled": true
|
||||
},
|
||||
"subagent": {
|
||||
"enabled": true,
|
||||
"agents": {
|
||||
"svelte-file-editor": {
|
||||
"model": "other-model", // defaults to the same as main agent,
|
||||
"temperature": 1, // default to unset
|
||||
"top_p": 0.7, // default to unset,
|
||||
"maxSteps": 20 // default to unlimited
|
||||
}
|
||||
}
|
||||
},
|
||||
"skills": {
|
||||
"enabled": true // it can also be an array of all the skills to enable like ['svelte-core-bestpractices']
|
||||
},
|
||||
"instructions": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
...but if you prefer, you can enable only the subagent, only the MCP, only the skills (`enabled` supports both a boolean or an array containing the name of all the skills to enable), or configure the kind of MCP server you want to use (`local` or `remote`).
|
||||
|
||||
You can place this file in `./.opencode/svelte.json` (in your project), in `~/.config/opencode/svelte.json` or, if you have an `OPENCODE_CONFIG_DIR` environment variable specified, at `$OPENCODE_CONFIG_DIR/svelte.json`.
|
||||
@@ -1,11 +0,0 @@
|
||||
---
|
||||
title: Subagent
|
||||
---
|
||||
|
||||
The Svelte plugin includes a specialized subagent called `svelte-file-editor` designed for creating, editing, and reviewing Svelte files.
|
||||
|
||||
## Benefits
|
||||
|
||||
The subagent has access to its own context window, allowing it to fetch the documentation, iterate with the `svelte-autofixer` tool and write to the file system without wasting context in the main agent.
|
||||
|
||||
The delegation should happen automatically when appropriate, but you can also explicitly request the subagent be used for Svelte-related tasks.
|
||||
67
documentation/docs/50-subagents/.generated/subagent.md
Normal file
67
documentation/docs/50-subagents/.generated/subagent.md
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
name: svelte-file-editor
|
||||
description: Specialized Svelte 5 code editor. MUST BE USED PROACTIVELY when creating, editing, or reviewing any .svelte file or .svelte.ts/.svelte.js module and MUST use the tools from the MCP server or the `svelte-file-editor` skill if they are available. Fetches relevant documentation and validates code using the Svelte MCP server tools.
|
||||
---
|
||||
|
||||
You are a Svelte 5 expert responsible for writing, editing, and validating Svelte components and modules. You have access to the Svelte MCP server which provides documentation and code analysis tools. Always use the tools from the svelte MCP server to fetch documentation with `get_documentation` and validating the code with `svelte_autofixer`. If the autofixer returns any issue or suggestions try to solve them.
|
||||
|
||||
If the MCP tools are not available you can use the `svelte-code-writer` skill to learn how to use the `@sveltejs/mcp` cli to access the same tools.
|
||||
|
||||
If the skill is not available you can run `npx @sveltejs/mcp@latest -y --help` to learn how to use it.
|
||||
|
||||
## Available MCP Tools
|
||||
|
||||
### 1. list-sections
|
||||
|
||||
Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths. Use this first to discover what documentation is available.
|
||||
|
||||
### 2. get-documentation
|
||||
|
||||
Retrieves full documentation for specified sections. Accepts a single section name or an array of section names. Use after `list-sections` to fetch relevant docs for the task at hand.
|
||||
|
||||
**Example sections:** `$state`, `$derived`, `$effect`, `$props`, `$bindable`, `snippets`, `routing`, `load functions`
|
||||
|
||||
### 3. svelte-autofixer
|
||||
|
||||
Analyzes Svelte code and returns suggestions to fix issues. Pass the component code directly to this tool. It will detect common mistakes like:
|
||||
|
||||
- Using `$effect` instead of `$derived` for computations
|
||||
- Missing cleanup in effects
|
||||
- Svelte 4 syntax (`on:click`, `export let`, `<slot>`)
|
||||
- Missing keys in `{#each}` blocks
|
||||
- And more
|
||||
|
||||
## Workflow
|
||||
|
||||
When invoked to work on a Svelte file:
|
||||
|
||||
### 1. Gather Context (if needed)
|
||||
|
||||
If you're uncertain about Svelte 5 syntax or patterns, use the MCP tools:
|
||||
|
||||
1. Call `list-sections` to see available documentation
|
||||
2. Call `get-documentation` with relevant section names
|
||||
|
||||
### 2. Read the Target File
|
||||
|
||||
Read the file to understand the current implementation.
|
||||
|
||||
### 3. Make Changes
|
||||
|
||||
Apply edits following Svelte 5 best practices:
|
||||
|
||||
### 4. Validate Changes
|
||||
|
||||
After editing, ALWAYS call `svelte-autofixer` with the updated code to check for issues.
|
||||
|
||||
### 5. Fix Any Issues
|
||||
|
||||
If the autofixer reports problems, fix them and re-validate until no issues remain.
|
||||
|
||||
## Output Format
|
||||
|
||||
After completing your work, provide:
|
||||
|
||||
1. Summary of changes made
|
||||
2. Any issues found and fixed by the autofixer
|
||||
3. Recommendations for further improvements (if any)
|
||||
20
documentation/docs/50-subagents/10-subagent.md
Normal file
20
documentation/docs/50-subagents/10-subagent.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
Since creating, editing or analyzing a Svelte file is an atomic operation we recommend creating a subagent that your main agent can invoke whenever it needs to interact with a Svelte component. Subagents use a separate context window, allowing them to fetch documentation, iterate with [`svelte-autofixer`](tools#svelte-autofixer) and write to the filesystem without wasting context in the main agent.
|
||||
|
||||
Delegation should happen automatically when appropriate, but you can also explicitly request the subagent be used for Svelte-related tasks.
|
||||
|
||||
You can write your own or take inspiration from the one available in the [`sveltejs/ai-tools`](https://github.com/sveltejs/ai-tools/tree/main/tools/agents) repository: a specialized subagent called `svelte-file-editor` designed for creating, editing, and reviewing Svelte files.
|
||||
|
||||
<details>
|
||||
<summary>View subagent definition</summary>
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
````markdown
|
||||
@include .generated/subagent.md
|
||||
````
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
</details>
|
||||
3
documentation/docs/50-subagents/index.md
Normal file
3
documentation/docs/50-subagents/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: Subagents
|
||||
---
|
||||
@@ -1,12 +1,12 @@
|
||||
---
|
||||
title: Overview
|
||||
title: Claude Code
|
||||
---
|
||||
|
||||
The open source [repository](https://github.com/sveltejs/ai-tools) containing the code for the MCP server is also a Claude Code Marketplace plugin.
|
||||
The open source [repository](https://github.com/sveltejs/ai-tools) containing the code for the MCP server is also a Claude Code [plugin marketplace](https://code.claude.com/docs/en/discover-plugins).
|
||||
|
||||
The marketplace allows you to install the `svelte` plugin which will give you the remote MCP server, [skills](skills) to instruct the LLM on how to properly write Svelte 5 code, and a specialized agent for editing Svelte files.
|
||||
|
||||
If possible, we recommend that you instruct the LLM to execute MCP calls with the agent (you can explicitly mention an agent in your message to delegate work to it) when creating or editing `.svelte` files or `.svelte.ts`/`.svelte.js` modules as it helps save context by handling Svelte-specific tasks more efficiently.
|
||||
If possible, we recommend that you instruct the LLM to execute MCP calls with the agent (you can explicitly mention an agent in your message to delegate work to it) when creating or editing `.svelte` files or `.svelte.ts`/`.svelte.js` modules — this will help save context by handling Svelte-specific tasks more efficiently.
|
||||
|
||||
## Installation
|
||||
|
||||
54
documentation/docs/60-plugins/20-opencode-plugin.md
Normal file
54
documentation/docs/60-plugins/20-opencode-plugin.md
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
title: OpenCode
|
||||
---
|
||||
|
||||
OpenCode has a [plugin system](https://opencode.ai/docs/plugins/) that allows developers to add MCP servers, agents and commands programmatically. Svelte has an OpenCode plugin published under `@sveltejs/opencode`.
|
||||
|
||||
## Installation
|
||||
|
||||
To install the plugin you can edit your [OpenCode config](https://opencode.ai/docs/config/) (either the global or the local one), adding `@sveltejs/opencode` to the list of plugins.
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"plugin": ["@sveltejs/opencode"]
|
||||
}
|
||||
```
|
||||
|
||||
That's it! You now have the Svelte [MCP server](mcp), [skills](skills), and the `svelte-file-editor` [subagent](subagent) configured for you.
|
||||
|
||||
## Configuration
|
||||
|
||||
By default, everything is enabled, but you can configure the plugin by adding a configuration file:
|
||||
|
||||
- locally, in `.opencode/svelte.json`
|
||||
- globally, in `~/.config/opencode/svelte.json` (or, if you have specified the environment variable, in `$OPENCODE_CONFIG_DIR/svelte.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://svelte.dev/opencode/schema.json",
|
||||
"mcp": {
|
||||
"type": "remote", // or "local" — defaults to remote
|
||||
"enabled": true
|
||||
},
|
||||
"subagent": {
|
||||
"enabled": true,
|
||||
"agents": {
|
||||
"svelte-file-editor": {
|
||||
"model": "<other-model>", // defaults to the same as main agent
|
||||
"temperature": 1, // defaults to unset
|
||||
"top_p": 0.7, // defaults to unset
|
||||
"maxSteps": 20 // defaults to unlimited
|
||||
}
|
||||
}
|
||||
},
|
||||
"skills": {
|
||||
// this can be `true`, or an array of skills to enable
|
||||
// e.g. ["svelte-core-bestpractices"]
|
||||
"enabled": true
|
||||
},
|
||||
"instructions": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
25
documentation/docs/60-plugins/30-cursor-plugin.md
Normal file
25
documentation/docs/60-plugins/30-cursor-plugin.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: Cursor
|
||||
---
|
||||
|
||||
Cursor has a [plugin system](https://cursor.com/docs/plugins) that can bundle rules, skills, agents, commands, MCP servers, and hooks.
|
||||
|
||||
The Svelte plugin gives you the remote Svelte MCP server, Cursor [skills](skills), an always-on rule that tells the model how to use the Svelte MCP tools correctly, and the `svelte-file-editor` subagent for working on `.svelte` files and `.svelte.ts`/`.svelte.js` modules. The source is available in the [`sveltejs/ai-tools`](https://github.com/sveltejs/ai-tools/tree/main/plugins/cursor/svelte) repo.
|
||||
|
||||
## Installation
|
||||
|
||||
Install the plugin from the [Cursor Marketplace](https://cursor.com/marketplace/svelte) with the following command:
|
||||
|
||||
```
|
||||
/add-plugin svelte
|
||||
```
|
||||
|
||||
Plugins can be installed either for the current project or at user level.
|
||||
|
||||
Once installed, Cursor will discover the plugin components automatically:
|
||||
|
||||
- the Svelte MCP server is added from the plugin's `.mcp.json`
|
||||
- rules and skills appear in Cursor's rules UI
|
||||
- the `svelte-file-editor` agent becomes available in chat
|
||||
|
||||
> [!NOTE] The Cursor CLI does not support plugins yet. Plugin support in [Cloud Agents](https://cursor.com/docs/cloud-agent) is limited to MCP servers.
|
||||
3
documentation/docs/60-plugins/index.md
Normal file
3
documentation/docs/60-plugins/index.md
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
title: Plugins
|
||||
---
|
||||
@@ -22,6 +22,7 @@
|
||||
"generate-summaries": "pnpm --filter @sveltejs/mcp-server run generate-summaries",
|
||||
"generate-prompt-docs": "node --import node-resolve-ts/register scripts/update-docs-prompts.ts",
|
||||
"generate-skill-docs": "node --import node-resolve-ts/register scripts/update-docs-skills.ts",
|
||||
"generate-subagent-docs": "cp ./tools/agents/svelte-file-editor.md ./documentation/docs/50-subagents/.generated/subagent.md",
|
||||
"debug:generate-summaries": "pnpm --filter @sveltejs/mcp-server run debug:generate-summaries",
|
||||
"release": "pnpm --filter @sveltejs/mcp run build && changeset publish",
|
||||
"changeset:version": "changeset version && pnpm --filter @sveltejs/mcp run update:version && git add --all",
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"name": "@sveltejs/mcp-schema",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"exports": {
|
||||
".": "./src/index.js",
|
||||
"./utils": "./src/utils.js",
|
||||
"./schema": "./src/schema.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"drizzle-orm": "catalog:orm"
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @import * as schema from './schema.js'
|
||||
*/
|
||||
export * from './schema.js';
|
||||
|
||||
/**
|
||||
* @typedef {typeof schema} Schema
|
||||
*/
|
||||
@@ -1,82 +0,0 @@
|
||||
import { integer, sqliteTable, text } from 'drizzle-orm/sqlite-core';
|
||||
import { float_32_array } from './utils.js';
|
||||
|
||||
/**
|
||||
* NOTE: if you modify a schema adding a vector column you need to manually add this
|
||||
*
|
||||
* CREATE INDEX IF NOT EXISTS name_of_the_index
|
||||
* ON `name_of_the_table` (
|
||||
* libsql_vector_idx(name_of_the_column, 'metric=cosine')
|
||||
* )
|
||||
*
|
||||
* to the generated migration file
|
||||
*/
|
||||
|
||||
export const distillations = sqliteTable('distillations', {
|
||||
id: integer('id').primaryKey(),
|
||||
preset_name: text('preset_name').notNull(),
|
||||
version: text('version').notNull(),
|
||||
content: text('content').notNull(),
|
||||
size_kb: integer('size_kb').notNull(),
|
||||
document_count: integer('document_count').notNull(),
|
||||
distillation_job_id: integer('distillation_job_id').references(() => distillation_jobs.id),
|
||||
created_at: integer('created_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export const distillation_jobs = sqliteTable('distillation_jobs', {
|
||||
id: integer('id').primaryKey(),
|
||||
preset_name: text('preset_name').notNull(),
|
||||
batch_id: text('batch_id'),
|
||||
status: text('status', { enum: ['pending', 'processing', 'completed', 'failed'] }).notNull(),
|
||||
model_used: text('model_used').notNull(),
|
||||
total_files: integer('total_files').notNull(),
|
||||
processed_files: integer('processed_files').notNull().default(0),
|
||||
successful_files: integer('successful_files').notNull().default(0),
|
||||
minimize_applied: integer('minimize_applied', { mode: 'boolean' }).notNull().default(false),
|
||||
total_input_tokens: integer('total_input_tokens').notNull().default(0),
|
||||
total_output_tokens: integer('total_output_tokens').notNull().default(0),
|
||||
started_at: integer('started_at', { mode: 'timestamp' }),
|
||||
completed_at: integer('completed_at', { mode: 'timestamp' }),
|
||||
error_message: text('error_message'),
|
||||
metadata: text('metadata', { mode: 'json' }).notNull().default({}),
|
||||
created_at: integer('created_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
updated_at: integer('updated_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export const content = sqliteTable('content', {
|
||||
id: integer('id').primaryKey(),
|
||||
path: text('path').notNull(),
|
||||
filename: text('filename').notNull(),
|
||||
content: text('content').notNull(),
|
||||
size_bytes: integer('size_bytes').notNull(),
|
||||
embeddings: float_32_array('embeddings', { dimensions: 1024 }),
|
||||
metadata: text('metadata', { mode: 'json' }).notNull().default({}),
|
||||
created_at: integer('created_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
updated_at: integer('updated_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
});
|
||||
|
||||
export const content_distilled = sqliteTable('content_distilled', {
|
||||
id: integer('id').primaryKey(),
|
||||
path: text('path').notNull(),
|
||||
filename: text('filename').notNull(),
|
||||
content: text('content').notNull(),
|
||||
size_bytes: integer('size_bytes').notNull(),
|
||||
embeddings: float_32_array('embeddings', { dimensions: 1024 }),
|
||||
metadata: text('metadata', { mode: 'json' }).notNull().default({}),
|
||||
created_at: integer('created_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
updated_at: integer('updated_at', { mode: 'timestamp' })
|
||||
.notNull()
|
||||
.$defaultFn(() => new Date()),
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
/**
|
||||
* @import { Column } from 'drizzle-orm';
|
||||
*/
|
||||
import { sql } from 'drizzle-orm';
|
||||
import { customType } from 'drizzle-orm/sqlite-core';
|
||||
|
||||
/**
|
||||
* Helper function to convert an array of embeddings into a format that can be inserted into a LibSQL vector column.
|
||||
* @param {number[]} arr The embeddings array.
|
||||
*/
|
||||
export function vector(arr) {
|
||||
return sql`vector32(${JSON.stringify(arr)})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to calculate the distance between a vector column and an array of embeddings and return it as a columns.
|
||||
* @param {Column} column The drizzle column representing the vector.
|
||||
* @param {number} arr The embeddings array.
|
||||
* @param {string} as The name of the returned column. Default is 'distance'.
|
||||
*
|
||||
* @example
|
||||
* await db.select({
|
||||
* id: vector_table.id,
|
||||
* text: vector_table.text,
|
||||
* distance: distance(vector_table.vector, await get_embeddings(sentence)),
|
||||
* })
|
||||
* .from(vector_table)
|
||||
* .orderBy(sql`distance`)
|
||||
* .execute();
|
||||
*/
|
||||
export function distance(column, arr, as = 'distance') {
|
||||
return /** @type {typeof sql<number>} */ (
|
||||
sql
|
||||
)`CASE ${column} ISNULL WHEN 1 THEN 1 ELSE vector_distance_cos(${column}, vector32(${JSON.stringify(arr)})) END`.as(
|
||||
as,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom drizzle type to use the LibSQL vector column type.
|
||||
*/
|
||||
export const float_32_array = /** @type {typeof customType<{
|
||||
data: number[];
|
||||
config: { dimensions: number };
|
||||
configRequired: true;
|
||||
driverData: Buffer;
|
||||
}>} */ (customType)({
|
||||
dataType(config) {
|
||||
return `F32_BLOB(${config.dimensions})`;
|
||||
},
|
||||
/**
|
||||
* @param {Buffer} value
|
||||
*/
|
||||
fromDriver(value) {
|
||||
return Array.from(new Float32Array(value.buffer));
|
||||
},
|
||||
/**
|
||||
*
|
||||
* @param {number[]} value
|
||||
* @returns
|
||||
*/
|
||||
toDriver(value) {
|
||||
return vector(value);
|
||||
},
|
||||
});
|
||||
@@ -17,12 +17,8 @@
|
||||
".": "./src/index.ts",
|
||||
"./handlers": "./src/mcp/handlers/tools/handlers.ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"drizzle-orm": "^0.45.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@mcp-ui/server": "catalog:ai",
|
||||
"@sveltejs/mcp-schema": "workspace:^",
|
||||
"@tmcp/adapter-valibot": "catalog:tmcp",
|
||||
"@tmcp/transport-in-memory": "catalog:tmcp",
|
||||
"@typescript-eslint/parser": "catalog:lint",
|
||||
|
||||
@@ -775,5 +775,16 @@ describe('add_autofixers_issues', () => {
|
||||
`You are reading the stateful variable "$x" with a "$" prefix. Stateful variables are not stores and should be read without the "$". Please read it as a normal variable "x"`,
|
||||
);
|
||||
});
|
||||
|
||||
// https://github.com/sveltejs/ai-tools/issues/200
|
||||
it('should not crash when reading $-prefixed identifier for variable initialized with member expression', () => {
|
||||
expect(() =>
|
||||
run_autofixers_on_code(`<div>{$x}</div>
|
||||
|
||||
<script>
|
||||
const x = foo.bar;
|
||||
</script>`),
|
||||
).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import { ValibotJsonSchemaAdapter } from '@tmcp/adapter-valibot';
|
||||
import { McpServer } from 'tmcp';
|
||||
import { setup_prompts, setup_resources, setup_tools } from './handlers/index.js';
|
||||
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
|
||||
import type { Schema } from '@sveltejs/mcp-schema';
|
||||
import { icons } from './icons/index.js';
|
||||
|
||||
export const server = new McpServer(
|
||||
@@ -25,7 +23,6 @@ export const server = new McpServer(
|
||||
'This is the official Svelte MCP server. It MUST be used whenever svelte development is involved. It can provide official documentation, code examples and correct your code. After you correct the component call this tool again to confirm all the issues are fixed.',
|
||||
},
|
||||
).withContext<{
|
||||
db: LibSQLDatabase<Schema>;
|
||||
track?: (sessionId: string, event: string, extra?: string) => Promise<void>;
|
||||
}>();
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ export function parse(code: string, file_path: string) {
|
||||
return this.all_references.find((r) => r.identifier === id);
|
||||
},
|
||||
is_rune(call: CallExpression, rune?: (typeof runes)[number][]) {
|
||||
// it should always be a call expression but we check just in case because sometimes it's any and TS doesn't complain
|
||||
if (call.type !== 'CallExpression') return false;
|
||||
if (call.callee.type !== 'Identifier' && call.callee.type !== 'MemberExpression')
|
||||
return false;
|
||||
const id = call.callee.type === 'Identifier' ? call.callee : call.callee.object;
|
||||
|
||||
673
pnpm-lock.yaml
generated
673
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -24,10 +24,6 @@ catalogs:
|
||||
prettier-plugin-svelte: ^3.3.3
|
||||
svelte-eslint-parser: ^1.4.0
|
||||
typescript-eslint: ^8.44.0
|
||||
orm:
|
||||
'@libsql/client': ^0.17.0
|
||||
drizzle-kit: ^0.31.0
|
||||
drizzle-orm: ^0.45.0
|
||||
svelte:
|
||||
'@sveltejs/adapter-vercel': ^6.0.0
|
||||
'@sveltejs/kit': ^2.42.2
|
||||
|
||||
@@ -3,7 +3,7 @@ import path from 'node:path';
|
||||
|
||||
const OPENCODE_PKG_DIR = './packages/opencode';
|
||||
const TOOLS_DIR = './tools';
|
||||
const DOCS_AGENTS_DIR = './documentation/docs/10-introduction/.generated';
|
||||
const DOCS_AGENTS_DIR = './documentation/docs/20-instructions/.generated';
|
||||
|
||||
/**
|
||||
* Sync skills from tools/ to opencode package (direct copy)
|
||||
|
||||
@@ -29,6 +29,6 @@ ${await module.generate_for_docs()}
|
||||
`;
|
||||
}
|
||||
|
||||
const generated_dir = './documentation/docs/30-capabilities/.generated';
|
||||
const generated_dir = './documentation/docs/30-mcp/.generated';
|
||||
await fs.mkdir(generated_dir, { recursive: true });
|
||||
await fs.writeFile(path.join(generated_dir, 'prompts.md'), content.trim() + '\n');
|
||||
|
||||
@@ -87,6 +87,6 @@ ${fence}
|
||||
}
|
||||
}
|
||||
|
||||
const generated_dir = './documentation/docs/60-skills/.generated';
|
||||
const generated_dir = './documentation/docs/40-skills/.generated';
|
||||
await fs.mkdir(generated_dir, { recursive: true });
|
||||
await fs.writeFile(path.join(generated_dir, 'skills.md'), content.trim() + '\n');
|
||||
|
||||
Reference in New Issue
Block a user