mirror of
https://github.com/sveltejs/ai-tools.git
synced 2026-07-04 03:19:38 +08:00
Compare commits
5 Commits
@sveltejs/
...
js-api-and
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
77c1728ab1 | ||
|
|
83e9d6583a | ||
|
|
5d8a85c2e3 | ||
|
|
eac75d3629 | ||
|
|
59abf83bdb |
@@ -7,5 +7,5 @@
|
||||
"access": "public",
|
||||
"baseBranch": "main",
|
||||
"updateInternalDependencies": "patch",
|
||||
"ignore": ["!@sveltejs/mcp", "!@sveltejs/opencode"]
|
||||
"ignore": ["!@sveltejs/mcp"]
|
||||
}
|
||||
|
||||
5
.changeset/moody-rules-relate.md
Normal file
5
.changeset/moody-rules-relate.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@sveltejs/mcp': patch
|
||||
---
|
||||
|
||||
feat: expose tools as JS api + cli
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "svelte",
|
||||
"owner": {
|
||||
"name": "Svelte"
|
||||
},
|
||||
"plugins": [
|
||||
{
|
||||
"name": "svelte",
|
||||
"source": "./plugins/svelte",
|
||||
"description": "A plugin for all things Svelte development, MCP, skills, and more.",
|
||||
"lspServers": {
|
||||
"svelte": {
|
||||
"command": "svelte-language-server",
|
||||
"args": ["--stdio"],
|
||||
"extensionToLanguage": {
|
||||
".svelte": "svelte"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
4
.github/workflows/check.yml
vendored
4
.github/workflows/check.yml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.28.2
|
||||
version: 10.26.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.28.2
|
||||
version: 10.26.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
4
.github/workflows/publish-any-commit.yml
vendored
4
.github/workflows/publish-any-commit.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- run: corepack enable
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
cache: 'pnpm'
|
||||
@@ -20,4 +20,4 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- run: pnpm dlx pkg-pr-new publish --compact './packages/mcp-stdio' './packages/opencode' --pnpm
|
||||
- run: pnpm dlx pkg-pr-new publish --compact './packages/mcp-stdio' --pnpm
|
||||
|
||||
45
.github/workflows/release-svelte-skill.yml
vendored
45
.github/workflows/release-svelte-skill.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Release Svelte Code Writer Skill
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'plugins/svelte/skills/svelte-code-writer/**'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
permissions:
|
||||
contents: write
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'sveltejs/mcp'
|
||||
name: Release Svelte Code Writer Skill
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: checkout
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Get version from date
|
||||
id: version
|
||||
run: echo "version=$(date +'%Y.%m.%d-%H%M%S')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create zip
|
||||
run: |
|
||||
cd plugins/svelte/skills
|
||||
zip -r svelte-code-writer.zip svelte-code-writer/
|
||||
|
||||
- name: Create Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: svelte-code-writer-v${{ steps.version.outputs.version }}
|
||||
name: Svelte Code Writer Skill v${{ steps.version.outputs.version }}
|
||||
body: |
|
||||
Automated release of the Svelte Code Writer skill.
|
||||
|
||||
This release was triggered by changes to the `plugins/svelte/skills/svelte-code-writer/` directory.
|
||||
files: plugins/svelte/skills/svelte-code-writer.zip
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
7
.github/workflows/release.yml
vendored
7
.github/workflows/release.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
with:
|
||||
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
|
||||
fetch-depth: 0
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
package-manager-cache: false # pnpm is not installed yet
|
||||
@@ -39,11 +39,10 @@ jobs:
|
||||
PNPM_VER=$(jq -r '.packageManager | if .[0:5] == "pnpm@" then .[5:] else "packageManager in package.json does not start with pnpm@\n" | halt_error(1) end' package.json)
|
||||
echo installing pnpm version $PNPM_VER
|
||||
npm i -g pnpm@$PNPM_VER
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
package-manager-cache: true # caches pnpm via packageManager field in package.json
|
||||
cache: 'pnpm'
|
||||
- name: install
|
||||
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
|
||||
- name: build
|
||||
@@ -52,7 +51,7 @@ jobs:
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
# pinned for security, always review third party action code before updating
|
||||
uses: changesets/action@c48e67d110a68bc90ccf1098e9646092baacaa87 # v1.6.0
|
||||
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
|
||||
|
||||
84
.github/workflows/sync-opencode-skills.yml
vendored
84
.github/workflows/sync-opencode-skills.yml
vendored
@@ -1,84 +0,0 @@
|
||||
name: Sync OpenCode Skills
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'plugins/svelte/skills/**'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
sync-skills:
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'sveltejs/mcp'
|
||||
name: Sync Skills to OpenCode Package and Update Docs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: false # pnpm is not installed yet
|
||||
|
||||
- name: Install pnpm
|
||||
shell: bash
|
||||
run: |
|
||||
PNPM_VER=$(jq -r '.packageManager | if .[0:5] == "pnpm@" then .[5:] else "packageManager in package.json does not start with pnpm@\n" | halt_error(1) end' package.json)
|
||||
echo installing pnpm version $PNPM_VER
|
||||
npm i -g pnpm@$PNPM_VER
|
||||
|
||||
- name: Setup Node.js with pnpm cache
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: true # caches pnpm via packageManager field in package.json
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
|
||||
|
||||
- name: Sync skills folder
|
||||
run: pnpm sync-opencode-skills
|
||||
|
||||
- name: Generate skills documentation
|
||||
run: pnpm generate-skill-docs
|
||||
|
||||
- name: Check for changes
|
||||
id: git-check
|
||||
run: |
|
||||
git diff --exit-code packages/opencode/skills documentation/docs/60-skills/10-skills.md || echo "changed=true" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.git-check.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'chore: sync skills and update documentation'
|
||||
branch: chore/sync-opencode-skills
|
||||
delete-branch: true
|
||||
title: 'chore: sync skills and update documentation'
|
||||
body: |
|
||||
## Summary
|
||||
Automatically synced skills and updated documentation.
|
||||
|
||||
This PR was triggered by changes to the skills folder in `plugins/svelte/skills/`.
|
||||
|
||||
## Changes
|
||||
- Synced `packages/opencode/skills/` with latest skill definitions
|
||||
- Updated `documentation/docs/60-skills/10-skills.md` with latest skill documentation
|
||||
|
||||
## Generated by
|
||||
GitHub Action: Sync OpenCode Skills
|
||||
labels: |
|
||||
chore
|
||||
documentation
|
||||
automated
|
||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -18,10 +18,10 @@ jobs:
|
||||
- name: Setup pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10.28.2
|
||||
version: 10.26.1
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
78
.github/workflows/update-opencode-jsonschema.yml
vendored
78
.github/workflows/update-opencode-jsonschema.yml
vendored
@@ -1,78 +0,0 @@
|
||||
name: Update OpenCode JSON Schema
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'packages/opencode/config.ts'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-docs:
|
||||
# prevents this action from running on forks
|
||||
if: github.repository == 'sveltejs/mcp'
|
||||
name: Update OpenCode JSON Schema
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: false # pnpm is not installed yet
|
||||
|
||||
- name: Install pnpm
|
||||
shell: bash
|
||||
run: |
|
||||
PNPM_VER=$(jq -r '.packageManager | if .[0:5] == "pnpm@" then .[5:] else "packageManager in package.json does not start with pnpm@\n" | halt_error(1) end' package.json)
|
||||
echo installing pnpm version $PNPM_VER
|
||||
npm i -g pnpm@$PNPM_VER
|
||||
|
||||
- name: Setup Node.js with pnpm cache
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: true # caches pnpm via packageManager field in package.json
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
|
||||
|
||||
- name: Generate opencode JSON schema
|
||||
run: pnpm generate-opencode-jsonschema
|
||||
|
||||
- name: Check for changes
|
||||
id: git-check
|
||||
run: |
|
||||
git diff --exit-code packages/opencode/schema.json || echo "changed=true" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.git-check.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'docs: update opencode JSON schema'
|
||||
branch: docs/update-opencode-jsonschema
|
||||
delete-branch: true
|
||||
title: 'docs: update opencode JSON schema'
|
||||
body: |
|
||||
## Summary
|
||||
Automatically generated update for OpenCode JSON schema.
|
||||
|
||||
This PR was triggered by changes to the OpenCode configuration file `packages/opencode/config.ts`.
|
||||
|
||||
## Changes
|
||||
- Updated `packages/opencode/schema.json` with latest JSON schema
|
||||
|
||||
## Generated by
|
||||
GitHub Action: Update OpenCode JSON Schema
|
||||
labels: |
|
||||
automated
|
||||
7
.github/workflows/update-prompt-docs.yml
vendored
7
.github/workflows/update-prompt-docs.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: false # pnpm is not installed yet
|
||||
@@ -37,11 +37,10 @@ jobs:
|
||||
npm i -g pnpm@$PNPM_VER
|
||||
|
||||
- name: Setup Node.js with pnpm cache
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v6.2.0
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: 24
|
||||
package-manager-cache: true # caches pnpm via packageManager field in package.json
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile --prefer-offline --ignore-scripts
|
||||
@@ -56,7 +55,7 @@ jobs:
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.git-check.outputs.changed == 'true'
|
||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
|
||||
uses: peter-evans/create-pull-request@v8
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
commit-message: 'docs: update prompts documentation'
|
||||
|
||||
@@ -12,6 +12,4 @@ bun.lockb
|
||||
|
||||
# Claude Code
|
||||
.claude/
|
||||
.changeset/
|
||||
|
||||
/packages/opencode/schema.json
|
||||
.changeset/
|
||||
@@ -25,5 +25,22 @@ export async function handle({ event, resolve }) {
|
||||
await track(event, { session_id, ...(extra ? { extra } : {}) });
|
||||
},
|
||||
});
|
||||
// we are deploying on vercel the SSE connection will timeout after 5 minutes...for
|
||||
// the moment we are not sending back any notifications (logs, or list changed notifications)
|
||||
// so it's a waste of resources to keep a connection open that will error
|
||||
// after 5 minutes making the logs dirty. For this reason if we have a response from
|
||||
// the MCP server and it's a GET request we just return an empty response (it has to be
|
||||
// 200 or the MCP client will complain)
|
||||
if (mcp_response && event.request.method === 'GET') {
|
||||
try {
|
||||
return mcp_response;
|
||||
} finally {
|
||||
try {
|
||||
await mcp_response.body?.cancel();
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
return mcp_response ?? resolve(event);
|
||||
}
|
||||
|
||||
@@ -4,9 +4,4 @@ import { HttpTransport } from '@tmcp/transport-http';
|
||||
export const http_transport = new HttpTransport(server, {
|
||||
cors: true,
|
||||
path: '/mcp',
|
||||
// we are deploying on vercel the SSE connection will timeout after 5 minutes...for
|
||||
// the moment we are not sending back any notifications (logs, or list changed notifications)
|
||||
// so it's a waste of resources to keep a connection open that will error
|
||||
// after 5 minutes making the logs dirty.
|
||||
disableSse: true,
|
||||
});
|
||||
|
||||
@@ -45,27 +45,6 @@ command = "npx"
|
||||
args = ["-y", "@sveltejs/mcp"]
|
||||
```
|
||||
|
||||
## Copilot CLI
|
||||
|
||||
Use the Copilot CLI to interactively add the MCP server:
|
||||
|
||||
```bash
|
||||
/mcp add
|
||||
```
|
||||
|
||||
Alternatively, create or edit `~/.copilot/mcp-config.json` and add the following configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"svelte": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@sveltejs/mcp"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Gemini CLI
|
||||
|
||||
To include the local MCP version in Gemini CLI, simply run the following command:
|
||||
@@ -78,7 +57,7 @@ The `[scope]` must be `user`, `project` or `local`.
|
||||
|
||||
## OpenCode
|
||||
|
||||
You can automatically configure the MCP server using the [OpenCode plugin](opencode-plugin) (recommended). If you prefer to configure the MCP server manually, run:
|
||||
Run the command:
|
||||
|
||||
```bash
|
||||
opencode mcp add
|
||||
|
||||
@@ -16,8 +16,6 @@ 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).
|
||||
|
||||
## Claude Desktop
|
||||
|
||||
- Open Settings > Connectors
|
||||
@@ -36,26 +34,6 @@ experimental_use_rmcp_client = true
|
||||
url = "https://mcp.svelte.dev/mcp"
|
||||
```
|
||||
|
||||
## Copilot CLI
|
||||
|
||||
Use the Copilot CLI to interactively add the MCP server:
|
||||
|
||||
```bash
|
||||
/mcp add
|
||||
```
|
||||
|
||||
Alternatively, create or edit `~/.copilot/mcp-config.json` and add the following configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcpServers": {
|
||||
"svelte": {
|
||||
"url": "https://mcp.svelte.dev/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Gemini CLI
|
||||
|
||||
To use the remote MCP server with Gemini CLI, simply run the following command:
|
||||
@@ -68,7 +46,7 @@ The `[scope]` must be `user` or `project`.
|
||||
|
||||
## OpenCode
|
||||
|
||||
You can automatically configure the MCP server using the [OpenCode plugin](opencode-plugin) (recommended). If you prefer to configure the MCP server manually, run:
|
||||
Run the command:
|
||||
|
||||
```bash
|
||||
opencode mcp add
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: Claude Code Plugin
|
||||
---
|
||||
@@ -1,23 +0,0 @@
|
||||
---
|
||||
title: Overview
|
||||
---
|
||||
|
||||
The open source [repository](https://github.com/sveltejs/mcp) containing the code for the MCP server is also a Claude Code Marketplace plugin.
|
||||
|
||||
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.
|
||||
|
||||
## Installation
|
||||
|
||||
To add the repository as a marketplace, launch Claude Code and type the following:
|
||||
|
||||
```bash
|
||||
/plugin marketplace add sveltejs/mcp
|
||||
```
|
||||
|
||||
Then, install the Svelte plugin:
|
||||
|
||||
```bash
|
||||
/plugin install svelte
|
||||
```
|
||||
@@ -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.
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: OpenCode Plugin
|
||||
---
|
||||
@@ -1,42 +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]() (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://raw.githubusercontent.com/sveltejs/mcp/refs/heads/main/packages/opencode/schema.json",
|
||||
"mcp": {
|
||||
"type": "remote",
|
||||
"enabled": true
|
||||
},
|
||||
"subagent": {
|
||||
"enabled": true
|
||||
},
|
||||
"skills": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
...but if you prefer, you can enable only the subagent, only the MCP, only the skills, or configure the kind of MCP server you want to use (`local` or `remote`).
|
||||
|
||||
You can place this file 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.
|
||||
@@ -1,86 +0,0 @@
|
||||
---
|
||||
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.
|
||||
|
||||
You can download the latest skills from the [releases page](https://github.com/sveltejs/mcp/releases) or find them in the [`plugins/svelte/skills`](https://github.com/sveltejs/mcp/tree/main/plugins/svelte/skills) folder.
|
||||
|
||||
## `svelte-code-writer`
|
||||
|
||||
CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating or editing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
|
||||
|
||||
<a href="https://github.com/sveltejs/mcp/releases?q=svelte-code-writer" target="_blank" rel="noopener noreferrer">Open Releases page</a>
|
||||
|
||||
<details>
|
||||
<summary>View skill content</summary>
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
````markdown
|
||||
# Svelte 5 Code Writer
|
||||
|
||||
## CLI Tools
|
||||
|
||||
You have access to `@sveltejs/mcp` CLI for Svelte-specific assistance. Use these commands via `npx`:
|
||||
|
||||
### List Documentation Sections
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp list-sections
|
||||
```
|
||||
|
||||
Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths.
|
||||
|
||||
### Get Documentation
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp get-documentation "<section1>,<section2>,..."
|
||||
```
|
||||
|
||||
Retrieves full documentation for specified sections. Use after `list-sections` to fetch relevant docs.
|
||||
|
||||
**Example:**
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp get-documentation "$state,$derived,$effect"
|
||||
```
|
||||
|
||||
### Svelte Autofixer
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp svelte-autofixer "<code_or_path>" [options]
|
||||
```
|
||||
|
||||
Analyzes Svelte code and suggests fixes for common issues.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `--async` - Enable async Svelte mode (default: false)
|
||||
- `--svelte-version` - Target version: 4 or 5 (default: 5)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Analyze inline code (escape $ as \$)
|
||||
npx @sveltejs/mcp svelte-autofixer '<script>let count = \$state(0);</script>'
|
||||
|
||||
# Analyze a file
|
||||
npx @sveltejs/mcp svelte-autofixer ./src/lib/Component.svelte
|
||||
|
||||
# Target Svelte 4
|
||||
npx @sveltejs/mcp svelte-autofixer ./Component.svelte --svelte-version 4
|
||||
```
|
||||
|
||||
**Important:** When passing code with runes (`$state`, `$derived`, etc.) via the terminal, escape the `$` character as `\$` to prevent shell variable substitution.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Uncertain about syntax?** Run `list-sections` then `get-documentation` for relevant topics
|
||||
2. **Reviewing/debugging?** Run `svelte-autofixer` on the code to detect issues
|
||||
3. **Always validate** - Run `svelte-autofixer` before finalizing any Svelte component
|
||||
````
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
</details>
|
||||
@@ -1,3 +0,0 @@
|
||||
---
|
||||
title: Skills
|
||||
---
|
||||
@@ -3,7 +3,7 @@
|
||||
"version": "0.0.1",
|
||||
"description": "The official Svelte MCP server implementation",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@10.28.2",
|
||||
"packageManager": "pnpm@10.26.1",
|
||||
"scripts": {
|
||||
"build": "pnpm -r run build",
|
||||
"dev": "pnpm --filter @sveltejs/mcp-remote run dev",
|
||||
@@ -18,14 +18,11 @@
|
||||
"test": "npm run test:unit -- --run",
|
||||
"test:watch": "npm run test:unit -- --watch",
|
||||
"inspect": "pnpm mcp-inspector",
|
||||
"generate-opencode-jsonschema": "pnpm --filter @sveltejs/opencode run generate-schema",
|
||||
"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",
|
||||
"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",
|
||||
"sync-opencode-skills": "rm -rf packages/opencode/skills && cp -r plugins/svelte/skills packages/opencode/skills"
|
||||
"changeset:version": "changeset version && pnpm --filter @sveltejs/mcp run update:version && git add --all"
|
||||
},
|
||||
"keywords": [
|
||||
"svelte",
|
||||
|
||||
@@ -35,7 +35,6 @@ function base_config(svelte_config: Config): ESLint.Options['baseConfig'] {
|
||||
'svelte/prefer-writable-derived': 'warn',
|
||||
'svelte/require-event-dispatcher-types': 'warn',
|
||||
'svelte/require-store-reactive-access': 'warn',
|
||||
'svelte/no-inspect': 'off',
|
||||
},
|
||||
|
||||
languageOptions: {
|
||||
|
||||
@@ -58,7 +58,7 @@ describe('playground-link tool', () => {
|
||||
type: 'resource',
|
||||
resource: expect.objectContaining({
|
||||
uri: 'ui://svelte/playground-link',
|
||||
mimeType: 'text/html;profile=mcp-app',
|
||||
mimeType: 'text/uri-list',
|
||||
_meta: { 'mcpui.dev/ui-preferred-frame-size': ['100%', '1200px'] },
|
||||
text: expect.stringMatching(/^https:\/\/svelte\.dev\/playground\/embed#H4sIA/),
|
||||
}),
|
||||
@@ -67,24 +67,6 @@ describe('playground-link tool', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should have tool _meta with resource URI for MCP Apps hosts', async () => {
|
||||
const tools = await session.listTools();
|
||||
const playground_tool = tools.tools.find((t) => t.name === 'playground-link');
|
||||
expect(playground_tool).toBeDefined();
|
||||
expect(playground_tool?._meta).toStrictEqual({
|
||||
ui: { resourceUri: 'ui://svelte/playground-link' },
|
||||
});
|
||||
});
|
||||
|
||||
it('should expose a resource for MCP Apps hosts', async () => {
|
||||
const resources = await session.listResources();
|
||||
const playground_resource = resources.resources.find(
|
||||
(r) => r.uri === 'ui://svelte/playground-link',
|
||||
);
|
||||
expect(playground_resource).toBeDefined();
|
||||
expect(playground_resource?.name).toBe('playground-link-ui');
|
||||
});
|
||||
|
||||
it('should not create a playground link if App.svelte is missing', async () => {
|
||||
const result = await session.callTool<{ url: string }>('playground-link', {
|
||||
name: 'My Playground',
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { createUIResource } from '@mcp-ui/server';
|
||||
import { tool } from 'tmcp/utils';
|
||||
import type { SvelteMcp } from '../../index.js';
|
||||
import * as v from 'valibot';
|
||||
import { icons } from '../../icons/index.js';
|
||||
import type { SvelteMcp } from '../../index.js';
|
||||
import { createUIResource } from '@mcp-ui/server';
|
||||
import { tool } from 'tmcp/utils';
|
||||
|
||||
async function compress_and_encode_text(input: string) {
|
||||
const reader = new Blob([input]).stream().pipeThrough(new CompressionStream('gzip')).getReader();
|
||||
@@ -97,106 +97,7 @@ export async function playground_link_handler({
|
||||
};
|
||||
}
|
||||
|
||||
// Create the UI resource for MCP Apps hosts (with adapter)
|
||||
// This will be registered as a resource that MCP Apps hosts can fetch
|
||||
const playground_ui_resource = createUIResource({
|
||||
uri: 'ui://svelte/playground-link',
|
||||
encoding: 'text',
|
||||
resourceProps: {
|
||||
_meta: {
|
||||
ui: {
|
||||
csp: {
|
||||
connectDomains: ['https://svelte.dev'],
|
||||
resourceDomains: ['https://svelte.dev'],
|
||||
frameDomains: ['https://svelte.dev'],
|
||||
baseUriDomains: ['https://svelte.dev'],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
content: {
|
||||
type: 'rawHtml',
|
||||
// This is a placeholder HTML - the actual iframe URL will be set per-request
|
||||
// MCP Apps hosts receive the tool input/output via postMessage
|
||||
htmlString: `<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style>
|
||||
* { margin: 0; padding: 0; box-sizing: border-box; }
|
||||
html, body { width: 100%; height: 100%; }
|
||||
iframe { width: 100%; height: 100%; border: none; display: none; }
|
||||
.loading { display: flex; align-items: center; justify-content: center; height: 100%; font-family: system-ui, sans-serif; color: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="loading" id="loading">Loading playground...</div>
|
||||
<iframe id="playground" allow="clipboard-write"></iframe>
|
||||
<script>
|
||||
function size_changed() {
|
||||
const width = document.body.scrollWidth;
|
||||
window.parent.postMessage({
|
||||
jsonrpc: '2.0',
|
||||
method: 'ui/notifications/size-changed',
|
||||
params: {
|
||||
width,
|
||||
height: 800
|
||||
}
|
||||
}, '*');
|
||||
}
|
||||
// Signal that the widget is ready
|
||||
window.parent.postMessage({ type: 'ui-lifecycle-iframe-ready' }, '*');
|
||||
|
||||
// Listen for render data from the adapter (for MCP Apps hosts)
|
||||
window.addEventListener('message', (event) => {
|
||||
if (event.data.type === 'ui-lifecycle-iframe-render-data') {
|
||||
const renderData = event.data.payload.renderData || {};
|
||||
const toolOutput = renderData.toolOutput;
|
||||
|
||||
// The tool output contains the iframe URL
|
||||
if (toolOutput && toolOutput.structuredContent && toolOutput.structuredContent.url) {
|
||||
const iframe = document.getElementById('playground');
|
||||
const loading = document.getElementById('loading');
|
||||
// Convert the URL to embed URL
|
||||
const embedUrl = toolOutput.structuredContent.url.replace('/playground#', '/playground/embed#');
|
||||
iframe.src = embedUrl;
|
||||
iframe.style.display = 'block';
|
||||
iframe.addEventListener("load", () => {
|
||||
size_changed();
|
||||
});
|
||||
loading.style.display = 'none';
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>`,
|
||||
},
|
||||
uiMetadata: {
|
||||
'preferred-frame-size': ['100%', '1200px'],
|
||||
},
|
||||
adapters: {
|
||||
mcpApps: { enabled: true },
|
||||
},
|
||||
});
|
||||
|
||||
export function playground_link(server: SvelteMcp) {
|
||||
// Register the UI resource so MCP Apps hosts can fetch it
|
||||
server.resource(
|
||||
{
|
||||
name: 'playground-link-ui',
|
||||
description: 'UI resource for the Svelte Playground widget',
|
||||
uri: playground_ui_resource.resource.uri,
|
||||
icons,
|
||||
},
|
||||
() => {
|
||||
return {
|
||||
contents: [playground_ui_resource.resource],
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
server.tool(
|
||||
{
|
||||
name: 'playground-link',
|
||||
@@ -211,12 +112,6 @@ export function playground_link(server: SvelteMcp) {
|
||||
openWorldHint: false,
|
||||
},
|
||||
icons,
|
||||
// For MCP Apps hosts - points to the registered resource
|
||||
_meta: {
|
||||
ui: {
|
||||
resourceUri: playground_ui_resource.resource.uri,
|
||||
},
|
||||
},
|
||||
},
|
||||
async ({ files, name, tailwind }) => {
|
||||
if (server.ctx.sessionId && server.ctx.custom?.track) {
|
||||
@@ -230,7 +125,6 @@ export function playground_link(server: SvelteMcp) {
|
||||
type: 'text',
|
||||
text: JSON.stringify({ url: result.url }),
|
||||
},
|
||||
// Embedded resource for MCP-UI hosts (no adapter, uses externalUrl)
|
||||
createUIResource({
|
||||
uri: 'ui://svelte/playground-link',
|
||||
content: {
|
||||
|
||||
@@ -53,18 +53,6 @@ describe('svelte-autofixer tool', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should add suggestions for snippets declared in script tag', async () => {
|
||||
const content = await autofixer_tool_call(`<script>
|
||||
{#snippet my_snippet()}
|
||||
some content
|
||||
{/snippet}
|
||||
</script>`);
|
||||
expect(content.issues.length).toBeGreaterThan(0);
|
||||
expect(content.suggestions).toContain(
|
||||
"The code can't be compiled because a Javascript parse error. The error suggests you have a `{#snippet ...}` block inside the `<script>` tag. Snippets are template syntax and should be declared in the markup section of the component, not in the script. Move the snippet outside of the `<script>` tag. Snippets declared in the markup can also be accessed in the script tag in case you need them.",
|
||||
);
|
||||
});
|
||||
|
||||
it('should error out if async is true with a version less than 5', async () => {
|
||||
const content = await autofixer_tool_call(
|
||||
`<script>
|
||||
|
||||
@@ -75,21 +75,14 @@ export async function svelte_autofixer_handler({
|
||||
|
||||
await add_eslint_issues(content, code, +desired_svelte_version, filename, async);
|
||||
} catch (e: unknown) {
|
||||
const error = e as Error & { start?: { line: number; column: number }; frame?: string };
|
||||
const error = e as Error & { start?: { line: number; column: number } };
|
||||
content.issues.push(
|
||||
`${error.message} at line ${error.start?.line}, column ${error.start?.column}`,
|
||||
);
|
||||
if (error.message.includes('js_parse_error')) {
|
||||
// Check if the error frame contains template syntax that was incorrectly placed in the script tag
|
||||
if (error.frame?.includes('{#snippet')) {
|
||||
content.suggestions.push(
|
||||
"The code can't be compiled because a Javascript parse error. The error suggests you have a `{#snippet ...}` block inside the `<script>` tag. Snippets are template syntax and should be declared in the markup section of the component, not in the script. Move the snippet outside of the `<script>` tag. Snippets declared in the markup can also be accessed in the script tag in case you need them.",
|
||||
);
|
||||
} else {
|
||||
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)`.",
|
||||
);
|
||||
}
|
||||
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)`.",
|
||||
|
||||
@@ -1,35 +1,5 @@
|
||||
# @sveltejs/mcp
|
||||
|
||||
## 0.1.20
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: turn off no-inspect in eslint for mcp ([`2245cb2`](https://github.com/sveltejs/mcp/commit/2245cb2dc9e2d217869b6a800795ce59ffb40c51))
|
||||
|
||||
## 0.1.19
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- chore: update svelte ([`7447744`](https://github.com/sveltejs/mcp/commit/74477448cea44ec21684ea4d39f2c5c7133b5150))
|
||||
|
||||
## 0.1.18
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- feat: expose playground link as MCP App ([#138](https://github.com/sveltejs/mcp/pull/138))
|
||||
|
||||
## 0.1.17
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: add suggestion for snippets declared in script tag ([#132](https://github.com/sveltejs/mcp/pull/132))
|
||||
|
||||
## 0.1.16
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- feat: expose tools as JS api + cli ([#128](https://github.com/sveltejs/mcp/pull/128))
|
||||
|
||||
## 0.1.15
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@sveltejs/mcp",
|
||||
"version": "0.1.20",
|
||||
"version": "0.1.15",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"mcpName": "dev.svelte/mcp",
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"subfolder": "packages/mcp-stdio",
|
||||
"source": "github"
|
||||
},
|
||||
"version": "0.1.20",
|
||||
"version": "0.1.15",
|
||||
"websiteUrl": "https://svelte.dev/docs/mcp/overview",
|
||||
"icons": [
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
{
|
||||
"registryType": "npm",
|
||||
"identifier": "@sveltejs/mcp",
|
||||
"version": "0.1.20",
|
||||
"version": "0.1.15",
|
||||
"runtimeHint": "npx",
|
||||
"transport": {
|
||||
"type": "stdio"
|
||||
|
||||
@@ -19,6 +19,5 @@ export default defineConfig([
|
||||
treeshake: true,
|
||||
clean: true,
|
||||
target: 'esnext',
|
||||
inlineOnly: false,
|
||||
},
|
||||
]);
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# @sveltejs/opencode
|
||||
|
||||
## 0.1.1
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: actually push skills to right config path ([`c2c1b3e`](https://github.com/sveltejs/mcp/commit/c2c1b3e5e788b14eea17cd37a83ca55433cc4072))
|
||||
|
||||
## 0.1.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- feat: distribute skills through opencode plugin ([#151](https://github.com/sveltejs/mcp/pull/151))
|
||||
|
||||
## 0.0.3
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- chore: add README to opencode plugin ([`71295bc`](https://github.com/sveltejs/mcp/commit/71295bc11fb7bac6703e655f5fddead29967353c))
|
||||
|
||||
## 0.0.2
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- fix: show toast after a few seconds to avoid race condition ([`57e2d1d`](https://github.com/sveltejs/mcp/commit/57e2d1def1f5590d0a3dd6d269ac39f6397ffecf))
|
||||
@@ -1,75 +0,0 @@
|
||||
# @sveltejs/opencode
|
||||
|
||||
OpenCode plugin for Svelte that provides the Svelte MCP server, a specialized file editor subagent and instruction files.
|
||||
|
||||
## Installation
|
||||
|
||||
Add `@sveltejs/opencode` to your OpenCode config (either global or local):
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"plugin": ["@sveltejs/opencode"]
|
||||
}
|
||||
```
|
||||
|
||||
That's it! You now have the Svelte MCP server and the file editor subagent configured automatically.
|
||||
|
||||
## Features
|
||||
|
||||
### Svelte MCP Server
|
||||
|
||||
The plugin automatically configures the [Svelte MCP server](https://mcp.svelte.dev) which provides:
|
||||
|
||||
- **list-sections** - Discover available Svelte 5 and SvelteKit documentation sections
|
||||
- **get-documentation** - Retrieve full documentation content for specific sections
|
||||
- **svelte-autofixer** - Analyze Svelte code and get issues/suggestions
|
||||
- **playground-link** - Generate Svelte Playground links with provided code
|
||||
|
||||
### Svelte File Editor Subagent
|
||||
|
||||
A specialized subagent (`svelte-file-editor`) that is automatically used when creating, editing, or reviewing `.svelte`, `.svelte.ts`, or `.svelte.js` files. It fetches relevant documentation and validates code using the Svelte MCP server tools.
|
||||
|
||||
### Agent Instructions
|
||||
|
||||
The plugin injects instructions that teach the agent how to effectively use the Svelte MCP tools.
|
||||
|
||||
## Configuration
|
||||
|
||||
The default configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/sveltejs/mcp/refs/heads/main/packages/opencode/schema.json",
|
||||
"mcp": {
|
||||
"type": "remote",
|
||||
"enabled": true
|
||||
},
|
||||
"subagent": {
|
||||
"enabled": true
|
||||
},
|
||||
"instructions": {
|
||||
"enabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration Options
|
||||
|
||||
| Option | Type | Default | Description |
|
||||
| ---------------------- | ----------------------- | ---------- | -------------------------------------------------------------------------------- |
|
||||
| `mcp.type` | `"remote"` \| `"local"` | `"remote"` | Use the remote server at `mcp.svelte.dev` or run locally via `npx @sveltejs/mcp` |
|
||||
| `mcp.enabled` | `boolean` | `true` | Enable/disable the MCP server |
|
||||
| `subagent.enabled` | `boolean` | `true` | Enable/disable the Svelte file editor subagent |
|
||||
| `instructions.enabled` | `boolean` | `true` | Enable/disable agent instructions injection |
|
||||
|
||||
### Config File Location
|
||||
|
||||
Place your configuration at one of these locations:
|
||||
|
||||
- `~/.config/opencode/svelte.json` (global)
|
||||
- `$OPENCODE_CONFIG_DIR/svelte.json` (if `OPENCODE_CONFIG_DIR` is set, takes priority)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
@@ -1,159 +0,0 @@
|
||||
import type { PluginInput } from '@opencode-ai/plugin';
|
||||
import { existsSync, readFileSync } from 'fs';
|
||||
import { homedir } from 'os';
|
||||
import { join } from 'path';
|
||||
import * as v from 'valibot';
|
||||
|
||||
const default_config = {
|
||||
mcp: {
|
||||
type: 'remote' as 'remote' | 'local',
|
||||
enabled: true,
|
||||
},
|
||||
subagent: {
|
||||
enabled: true,
|
||||
},
|
||||
instructions: {
|
||||
enabled: true,
|
||||
},
|
||||
skills: {
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const config_schema = v.object({
|
||||
mcp: v.optional(
|
||||
v.object({
|
||||
type: v.optional(v.picklist(['remote', 'local'])),
|
||||
enabled: v.optional(v.boolean()),
|
||||
}),
|
||||
),
|
||||
subagent: v.optional(
|
||||
v.object({
|
||||
enabled: v.optional(v.boolean()),
|
||||
}),
|
||||
),
|
||||
instructions: v.optional(
|
||||
v.object({
|
||||
enabled: v.optional(v.boolean()),
|
||||
}),
|
||||
),
|
||||
skills: v.optional(
|
||||
v.object({
|
||||
enabled: v.optional(v.boolean()),
|
||||
}),
|
||||
),
|
||||
});
|
||||
|
||||
export type McpConfig = v.InferInput<typeof config_schema>;
|
||||
|
||||
const GLOBAL_CONFIG_DIR = join(homedir(), '.config', 'opencode');
|
||||
const GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, 'svelte.json');
|
||||
|
||||
interface ConfigLoadResult {
|
||||
data: Record<string, unknown> | null;
|
||||
parse_error?: string;
|
||||
}
|
||||
|
||||
function get_config_paths() {
|
||||
// Global: ~/.config/opencode/svelte.json
|
||||
let global_path: string | null = null;
|
||||
if (existsSync(GLOBAL_CONFIG_PATH)) {
|
||||
global_path = GLOBAL_CONFIG_PATH;
|
||||
}
|
||||
|
||||
// Custom config directory: $OPENCODE_CONFIG_DIR/svelte.json
|
||||
let config_dir_path: string | null = null;
|
||||
const opencode_config_dir = process.env.OPENCODE_CONFIG_DIR;
|
||||
if (opencode_config_dir) {
|
||||
const config_json = join(opencode_config_dir, 'svelte.json');
|
||||
if (existsSync(config_json)) {
|
||||
config_dir_path = config_json;
|
||||
}
|
||||
}
|
||||
|
||||
// returning config_dir first so it has higher priority
|
||||
return [config_dir_path, global_path];
|
||||
}
|
||||
|
||||
function load_config_file(config_path: string): ConfigLoadResult {
|
||||
let file_content: string;
|
||||
try {
|
||||
file_content = readFileSync(config_path, 'utf-8');
|
||||
} catch {
|
||||
// File doesn't exist or can't be read
|
||||
return { data: null };
|
||||
}
|
||||
|
||||
try {
|
||||
const parsed = JSON.parse(file_content);
|
||||
if (parsed === undefined || parsed === null) {
|
||||
return { data: null, parse_error: 'Config file is empty or invalid' };
|
||||
}
|
||||
return { data: parsed };
|
||||
} catch (error: unknown) {
|
||||
return {
|
||||
data: null,
|
||||
parse_error: error instanceof Error ? error.message : 'Failed to parse config',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function merge_with_defaults(user_config: Partial<McpConfig>): McpConfig {
|
||||
return {
|
||||
mcp: {
|
||||
...default_config.mcp,
|
||||
...user_config.mcp,
|
||||
},
|
||||
subagent: {
|
||||
...default_config.subagent,
|
||||
...user_config.subagent,
|
||||
},
|
||||
instructions: {
|
||||
...default_config.instructions,
|
||||
...user_config.instructions,
|
||||
},
|
||||
skills: {
|
||||
...default_config.skills,
|
||||
...user_config.skills,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function get_mcp_config(ctx: PluginInput) {
|
||||
const config_paths = get_config_paths();
|
||||
for (const path of config_paths) {
|
||||
if (path && existsSync(path)) {
|
||||
const result = load_config_file(path);
|
||||
if (result.parse_error) {
|
||||
setTimeout(() => {
|
||||
ctx.client.tui.showToast({
|
||||
body: {
|
||||
title: 'Svelte: Invalid opencode plugin config',
|
||||
message: `${result.parse_error}\nUsing default values`,
|
||||
variant: 'warning',
|
||||
duration: 7000,
|
||||
},
|
||||
});
|
||||
}, 7000);
|
||||
return default_config;
|
||||
}
|
||||
const parsed = v.safeParse(config_schema, result.data);
|
||||
if (parsed.success) {
|
||||
return merge_with_defaults(parsed.output);
|
||||
} else {
|
||||
setTimeout(() => {
|
||||
ctx.client.tui.showToast({
|
||||
body: {
|
||||
title: 'Svelte: Invalid opencode plugin config',
|
||||
message: `${result.parse_error}\nUsing default values`,
|
||||
variant: 'warning',
|
||||
duration: 7000,
|
||||
},
|
||||
});
|
||||
}, 7000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return default_config;
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
import type { Plugin } from '@opencode-ai/plugin';
|
||||
import { readdir } from 'node:fs/promises';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { get_mcp_config } from './config.js';
|
||||
|
||||
const current_dir = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export const svelte_plugin: Plugin = async (ctx) => {
|
||||
return {
|
||||
async config(input) {
|
||||
input.agent ??= {};
|
||||
input.mcp ??= {};
|
||||
input.instructions ??= [];
|
||||
// @ts-expect-error -- types are wrong in the opencode package...will fix there and remove this
|
||||
input.skills ??= {};
|
||||
// @ts-expect-error -- types are wrong in the opencode package...will fix there and remove this
|
||||
input.skills.paths ??= [];
|
||||
// by default we use svelte as the name for the svelte MCP server
|
||||
let svelte_mcp_name = 'svelte';
|
||||
// we loop over every mcp server to see if any of them is already the svelte MCP server
|
||||
for (const name in input.mcp) {
|
||||
const mcp = input.mcp[name];
|
||||
if (
|
||||
(mcp?.type === 'remote' && mcp.url.includes('https://mcp.svelte.dev/mcp')) ||
|
||||
(mcp?.type === 'local' &&
|
||||
mcp.command.some((cmd: string) => cmd.includes('@sveltejs/mcp')))
|
||||
) {
|
||||
// if we found the svelte MCP server, we store its name and break
|
||||
svelte_mcp_name = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const mcp_config = get_mcp_config(ctx);
|
||||
|
||||
if (mcp_config.instructions?.enabled !== false) {
|
||||
const instructions_dir = join(current_dir, 'instructions');
|
||||
const instructions_paths = await readdir(instructions_dir);
|
||||
input.instructions.push(...instructions_paths.map((file) => join(instructions_dir, file)));
|
||||
}
|
||||
|
||||
if (mcp_config.skills?.enabled !== false) {
|
||||
const skills_dir = join(current_dir, 'skills');
|
||||
// @ts-expect-error -- skills is a new opencode feature
|
||||
input.skills.paths.push(skills_dir);
|
||||
}
|
||||
|
||||
// if the user doesn't have the MCP server already we add one based on config
|
||||
if (!input.mcp[svelte_mcp_name] && mcp_config.mcp?.enabled !== false) {
|
||||
if (mcp_config.mcp?.type === 'remote') {
|
||||
input.mcp[svelte_mcp_name] = {
|
||||
type: 'remote',
|
||||
url: 'https://mcp.svelte.dev/mcp',
|
||||
};
|
||||
} else {
|
||||
input.mcp[svelte_mcp_name] = {
|
||||
type: 'local',
|
||||
command: ['npx', '-y', '@sveltejs/mcp'],
|
||||
};
|
||||
}
|
||||
}
|
||||
if (mcp_config.subagent?.enabled !== false) {
|
||||
// we add the editor subagent that will be used when editing Svelte files to prevent wasting context on the main agent
|
||||
input.agent['svelte-file-editor'] = {
|
||||
color: '#ff3e00',
|
||||
mode: 'subagent',
|
||||
prompt: `You are a specialized Svelte coder. 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 solve them before summarizing the changes for the main agent.`,
|
||||
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. Fetches relevant documentation and validates code using the Svelte MCP server tools.',
|
||||
permission: {
|
||||
bash: 'ask',
|
||||
edit: 'allow',
|
||||
webfetch: 'ask',
|
||||
},
|
||||
tools: {
|
||||
[`${svelte_mcp_name}_*`]: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
||||
};
|
||||
@@ -1,23 +0,0 @@
|
||||
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:
|
||||
|
||||
## Available MCP Tools:
|
||||
|
||||
### 1. list-sections
|
||||
|
||||
Use this FIRST to discover all available documentation sections. Returns a structured list with titles, use_cases, and paths.
|
||||
When asked about Svelte or SvelteKit topics, ALWAYS use this tool at the start of the chat to find relevant sections.
|
||||
|
||||
### 2. get-documentation
|
||||
|
||||
Retrieves full documentation content for specific sections. Accepts single or multiple sections.
|
||||
After calling the list-sections tool, you MUST analyze the returned documentation sections (especially the use_cases field) and then use the get-documentation tool to fetch ALL documentation sections that are relevant for the user's task.
|
||||
|
||||
### 3. svelte-autofixer
|
||||
|
||||
Analyzes Svelte code and returns issues and suggestions.
|
||||
You MUST use this tool whenever writing Svelte code before sending it to the user. Keep calling it until no issues or suggestions are returned.
|
||||
|
||||
### 4. playground-link
|
||||
|
||||
Generates a Svelte Playground link with the provided code.
|
||||
After completing the code, ask the user if they want a playground link. Only call this tool after user confirmation and NEVER if code was written to files in their project.
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"name": "@sveltejs/opencode",
|
||||
"version": "0.1.1",
|
||||
"type": "module",
|
||||
"license": "MIT",
|
||||
"homepage": "https://github.com/sveltejs/mcp#readme",
|
||||
"bugs": {
|
||||
"url": "https://github.com/sveltejs/mcp/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"check": "tsc --noEmit",
|
||||
"generate-schema": "node --import node-resolve-ts/register scripts/generate-schema.ts"
|
||||
},
|
||||
"files": [
|
||||
"index.ts",
|
||||
"config.ts",
|
||||
"instructions",
|
||||
"skills"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/sveltejs/mcp.git",
|
||||
"path": "packages/opencode"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"dependencies": {
|
||||
"valibot": "catalog:tooling"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@opencode-ai/plugin": "catalog:ai",
|
||||
"@valibot/to-json-schema": "catalog:tooling",
|
||||
"@types/node": "catalog:tooling"
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mcp": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"type": {
|
||||
"enum": [
|
||||
"remote",
|
||||
"local"
|
||||
]
|
||||
},
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"subagent": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"instructions": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
},
|
||||
"skills": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"type": "boolean"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
}
|
||||
},
|
||||
"required": [],
|
||||
"$schema": "http://json-schema.org/draft-07/schema#"
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
import { toJsonSchema } from '@valibot/to-json-schema';
|
||||
import { config_schema } from '../config.js';
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const json_schema = toJsonSchema(config_schema);
|
||||
|
||||
fs.writeFileSync(path.resolve('./schema.json'), JSON.stringify(json_schema, null, '\t'));
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
name: svelte-code-writer
|
||||
description: CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating or editing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
|
||||
---
|
||||
|
||||
# Svelte 5 Code Writer
|
||||
|
||||
## CLI Tools
|
||||
|
||||
You have access to `@sveltejs/mcp` CLI for Svelte-specific assistance. Use these commands via `npx`:
|
||||
|
||||
### List Documentation Sections
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp list-sections
|
||||
```
|
||||
|
||||
Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths.
|
||||
|
||||
### Get Documentation
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp get-documentation "<section1>,<section2>,..."
|
||||
```
|
||||
|
||||
Retrieves full documentation for specified sections. Use after `list-sections` to fetch relevant docs.
|
||||
|
||||
**Example:**
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp get-documentation "$state,$derived,$effect"
|
||||
```
|
||||
|
||||
### Svelte Autofixer
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp svelte-autofixer "<code_or_path>" [options]
|
||||
```
|
||||
|
||||
Analyzes Svelte code and suggests fixes for common issues.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `--async` - Enable async Svelte mode (default: false)
|
||||
- `--svelte-version` - Target version: 4 or 5 (default: 5)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Analyze inline code (escape $ as \$)
|
||||
npx @sveltejs/mcp svelte-autofixer '<script>let count = \$state(0);</script>'
|
||||
|
||||
# Analyze a file
|
||||
npx @sveltejs/mcp svelte-autofixer ./src/lib/Component.svelte
|
||||
|
||||
# Target Svelte 4
|
||||
npx @sveltejs/mcp svelte-autofixer ./Component.svelte --svelte-version 4
|
||||
```
|
||||
|
||||
**Important:** When passing code with runes (`$state`, `$derived`, etc.) via the terminal, escape the `$` character as `\$` to prevent shell variable substitution.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Uncertain about syntax?** Run `list-sections` then `get-documentation` for relevant topics
|
||||
2. **Reviewing/debugging?** Run `svelte-autofixer` on the code to detect issues
|
||||
3. **Always validate** - Run `svelte-autofixer` before finalizing any Svelte component
|
||||
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"include": ["index.ts", "config.ts", "scripts/*"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"name": "svelte",
|
||||
"description": "A plugin for all things related to Svelte development, MCP, skills, and more.",
|
||||
"version": "1.0.0",
|
||||
"author": {
|
||||
"name": "Svelte"
|
||||
},
|
||||
"lspServers": {
|
||||
"svelte": {
|
||||
"command": "svelte-language-server",
|
||||
"args": ["--stdio"],
|
||||
"extensionToLanguage": {
|
||||
".svelte": "svelte"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"mcpServers": {
|
||||
"svelte": {
|
||||
"type": "http",
|
||||
"url": "https://mcp.svelte.dev/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
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. Fetches relevant documentation and validates code using the Svelte MCP server tools.
|
||||
permissionMode: acceptEdits
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
## 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)
|
||||
@@ -1,66 +0,0 @@
|
||||
---
|
||||
name: svelte-code-writer
|
||||
description: CLI tools for Svelte 5 documentation lookup and code analysis. MUST be used whenever creating or editing any Svelte component (.svelte) or Svelte module (.svelte.ts/.svelte.js). If possible, this skill should be executed within the svelte-file-editor agent for optimal results.
|
||||
---
|
||||
|
||||
# Svelte 5 Code Writer
|
||||
|
||||
## CLI Tools
|
||||
|
||||
You have access to `@sveltejs/mcp` CLI for Svelte-specific assistance. Use these commands via `npx`:
|
||||
|
||||
### List Documentation Sections
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp list-sections
|
||||
```
|
||||
|
||||
Lists all available Svelte 5 and SvelteKit documentation sections with titles and paths.
|
||||
|
||||
### Get Documentation
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp get-documentation "<section1>,<section2>,..."
|
||||
```
|
||||
|
||||
Retrieves full documentation for specified sections. Use after `list-sections` to fetch relevant docs.
|
||||
|
||||
**Example:**
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp get-documentation "$state,$derived,$effect"
|
||||
```
|
||||
|
||||
### Svelte Autofixer
|
||||
|
||||
```bash
|
||||
npx @sveltejs/mcp svelte-autofixer "<code_or_path>" [options]
|
||||
```
|
||||
|
||||
Analyzes Svelte code and suggests fixes for common issues.
|
||||
|
||||
**Options:**
|
||||
|
||||
- `--async` - Enable async Svelte mode (default: false)
|
||||
- `--svelte-version` - Target version: 4 or 5 (default: 5)
|
||||
|
||||
**Examples:**
|
||||
|
||||
```bash
|
||||
# Analyze inline code (escape $ as \$)
|
||||
npx @sveltejs/mcp svelte-autofixer '<script>let count = \$state(0);</script>'
|
||||
|
||||
# Analyze a file
|
||||
npx @sveltejs/mcp svelte-autofixer ./src/lib/Component.svelte
|
||||
|
||||
# Target Svelte 4
|
||||
npx @sveltejs/mcp svelte-autofixer ./Component.svelte --svelte-version 4
|
||||
```
|
||||
|
||||
**Important:** When passing code with runes (`$state`, `$derived`, etc.) via the terminal, escape the `$` character as `\$` to prevent shell variable substitution.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Uncertain about syntax?** Run `list-sections` then `get-documentation` for relevant topics
|
||||
2. **Reviewing/debugging?** Run `svelte-autofixer` on the code to detect issues
|
||||
3. **Always validate** - Run `svelte-autofixer` before finalizing any Svelte component
|
||||
3200
pnpm-lock.yaml
generated
3200
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -5,9 +5,8 @@ packages:
|
||||
catalogs:
|
||||
ai:
|
||||
'@anthropic-ai/sdk': ^0.71.0
|
||||
'@mcp-ui/server': ^6.0.0
|
||||
'@modelcontextprotocol/inspector': ^0.19.0
|
||||
'@opencode-ai/plugin': ^1.1.44
|
||||
'@mcp-ui/server': ^5.12.0
|
||||
'@modelcontextprotocol/inspector': ^0.18.0
|
||||
lint:
|
||||
'@eslint/compat': ^2.0.0
|
||||
'@eslint/js': ^9.36.0
|
||||
@@ -19,24 +18,24 @@ catalogs:
|
||||
eslint-plugin-import: ^2.32.0
|
||||
eslint-plugin-pnpm: ^1.3.0
|
||||
eslint-plugin-svelte: ^3.12.5
|
||||
globals: ^17.0.0
|
||||
globals: ^16.0.0
|
||||
prettier: ^3.4.2
|
||||
prettier-plugin-svelte: ^3.3.3
|
||||
svelte-eslint-parser: ^1.4.0
|
||||
typescript-eslint: ^8.44.0
|
||||
orm:
|
||||
'@libsql/client': ^0.17.0
|
||||
'@libsql/client': ^0.15.0
|
||||
drizzle-kit: ^0.31.0
|
||||
drizzle-orm: ^0.45.0
|
||||
svelte:
|
||||
'@sveltejs/adapter-vercel': ^6.0.0
|
||||
'@sveltejs/kit': ^2.42.2
|
||||
'@sveltejs/vite-plugin-svelte': ^6.0.0
|
||||
svelte: ^5.47.0
|
||||
svelte: ^5.39.2
|
||||
svelte-check: ^4.0.0
|
||||
tmcp:
|
||||
'@tmcp/adapter-valibot': ^0.1.4
|
||||
'@tmcp/transport-http': ^0.8.4
|
||||
'@tmcp/transport-http': ^0.8.3
|
||||
'@tmcp/transport-in-memory': ^0.0.5
|
||||
'@tmcp/transport-stdio': ^0.4.0
|
||||
tmcp: ^1.19.0
|
||||
@@ -45,16 +44,15 @@ catalogs:
|
||||
'@svitejs/changesets-changelog-github-compact': ^1.2.0
|
||||
'@types/estree': ^1.0.8
|
||||
'@types/node': ^24.3.1
|
||||
'@valibot/to-json-schema': ^1.5.0
|
||||
'@vercel/analytics': ^1.5.0
|
||||
dotenv: ^17.2.3
|
||||
node-resolve-ts: ^1.0.2
|
||||
publint: ^0.3.13
|
||||
sade: 1.8.1
|
||||
ts-blank-space: ^0.7.0
|
||||
tsdown: ^0.20.0
|
||||
ts-blank-space: ^0.6.2
|
||||
tsdown: ^0.18.0
|
||||
typescript: ^5.0.0
|
||||
valibot: ^1.2.0
|
||||
valibot: ^1.1.0
|
||||
vite: ^7.0.4
|
||||
vite-plugin-devtools-json: ^1.0.0
|
||||
vitest: ^4.0.0
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
|
||||
interface SkillFrontmatter {
|
||||
name: string;
|
||||
description: string;
|
||||
}
|
||||
|
||||
function get_backtick_fence(content: string): string {
|
||||
const backtick_pattern = /`{3,}/g;
|
||||
let max_backticks = 3;
|
||||
|
||||
let match;
|
||||
while ((match = backtick_pattern.exec(content)) !== null) {
|
||||
max_backticks = Math.max(max_backticks, match[0].length);
|
||||
}
|
||||
|
||||
return '`'.repeat(max_backticks + 1);
|
||||
}
|
||||
|
||||
function parse_frontmatter(
|
||||
content: string,
|
||||
): { frontmatter: SkillFrontmatter; body: string } | null {
|
||||
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
||||
if (!match) return null;
|
||||
|
||||
const frontmatter_str = match[1];
|
||||
const body = match[2];
|
||||
|
||||
if (!frontmatter_str || body === undefined) return null;
|
||||
|
||||
const frontmatter: Record<string, string> = {};
|
||||
|
||||
for (const line of frontmatter_str.split('\n')) {
|
||||
const [key, ...value_parts] = line.split(':');
|
||||
if (key && value_parts.length > 0) {
|
||||
frontmatter[key.trim()] = value_parts.join(':').trim();
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
frontmatter: frontmatter as unknown as SkillFrontmatter,
|
||||
body: body.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
let content = `---
|
||||
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.
|
||||
|
||||
You can download the latest skills from the [releases page](https://github.com/sveltejs/mcp/releases) or find them in the [\`plugins/svelte/skills\`](https://github.com/sveltejs/mcp/tree/main/plugins/svelte/skills) folder.
|
||||
|
||||
`;
|
||||
|
||||
const skills_dir = './plugins/svelte/skills';
|
||||
const skill_dirs = (await fs.readdir(skills_dir)).filter((name) => !name.startsWith('.'));
|
||||
|
||||
for (const skill_name of skill_dirs) {
|
||||
const skill_path = path.join(skills_dir, skill_name, 'SKILL.md');
|
||||
|
||||
try {
|
||||
const skill_content = await fs.readFile(skill_path, 'utf-8');
|
||||
const parsed = parse_frontmatter(skill_content);
|
||||
|
||||
if (!parsed) {
|
||||
console.warn(`Warning: Could not parse frontmatter for ${skill_name}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
const { frontmatter, body } = parsed;
|
||||
const fence = get_backtick_fence(body);
|
||||
|
||||
content += `## \`${frontmatter.name}\`
|
||||
|
||||
${frontmatter.description}
|
||||
|
||||
<a href="https://github.com/sveltejs/mcp/releases?q=${frontmatter.name}" target="_blank" rel="noopener noreferrer">Open Releases page</a>
|
||||
|
||||
<details>
|
||||
<summary>View skill content</summary>
|
||||
|
||||
<!-- prettier-ignore-start -->
|
||||
${fence}markdown
|
||||
${body}
|
||||
${fence}
|
||||
<!-- prettier-ignore-end -->
|
||||
|
||||
</details>
|
||||
|
||||
`;
|
||||
} catch {
|
||||
console.warn(`Warning: Could not read skill at ${skill_path}`);
|
||||
}
|
||||
}
|
||||
|
||||
await fs.writeFile('./documentation/docs/60-skills/10-skills.md', content.trim() + '\n');
|
||||
Reference in New Issue
Block a user