Skip to content

Commit cf62286

Browse files
committed
fix: use data: uri for local icon & add icons to tools + resources + prompts
1 parent a4dfaab commit cf62286

File tree

10 files changed

+37
-10
lines changed

10 files changed

+37
-10
lines changed

.changeset/hip-cats-marry.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/mcp': patch
3+
---
4+
5+
fix: use `data:` uri for local icon & add icons to tools + resources + prompts

.vscode/mcp-snippets.code-snippets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"body": [
1313
"import type { SvelteMcp } from '../../index.js';",
1414
"import * as v from 'valibot';",
15+
"import { icons } from '../../icons/index.js';",
1516
"",
1617
"export function ${1:function_name}(server: SvelteMcp) {",
1718
"\t$0",
@@ -35,6 +36,7 @@
3536
"prefix": "!prompt",
3637
"body": [
3738
"import type { SvelteMcp } from '../../index.js';",
39+
"import { icons } from '../../icons/index.js';",
3840
"",
3941
"/**",
4042
" * Function that actually generates the prompt string. You can use this in the MCP server handler to generate the prompt, it can accept arguments",
@@ -69,6 +71,7 @@
6971
"\t\t\ttitle: '${2:title}',",
7072
"\t\t\tdescription:",
7173
"\t\t\t\t'${3:llm_description}',",
74+
"\t\t\ticons,",
7275
"\t\t},",
7376
"\t\tasync () => {",
7477
"\t\t\treturn {",

packages/mcp-server/src/mcp/handlers/prompts/svelte-task.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { SvelteMcp } from '../../index.js';
22
import * as v from 'valibot';
33
import { format_sections_list } from '../../utils.js';
4+
import { icons } from '../../icons/index.js';
45

56
/**
67
* Function that actually generates the prompt string. You can use this in the MCP server handler to generate the prompt, it can accept arguments
@@ -64,6 +65,7 @@ export function setup_svelte_task(server: SvelteMcp) {
6465
};
6566
},
6667
},
68+
icons,
6769
},
6870
async ({ task }) => {
6971
const available_docs = await format_sections_list();

packages/mcp-server/src/mcp/handlers/resources/doc-section.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { SvelteMcp } from '../../index.js';
22
import { get_sections, fetch_with_timeout } from '../../utils.js';
3+
import { icons } from '../../icons/index.js';
34

45
export async function list_sections(server: SvelteMcp) {
56
const sections = await get_sections();
@@ -42,6 +43,7 @@ export async function list_sections(server: SvelteMcp) {
4243
},
4344
},
4445
uri: 'svelte://{/slug*}.md',
46+
icons,
4547
},
4648
async (uri, { slug }) => {
4749
const section = sections.find((section) => {

packages/mcp-server/src/mcp/handlers/tools/get-documentation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { SvelteMcp } from '../../index.js';
22
import * as v from 'valibot';
33
import { get_sections, fetch_with_timeout, format_sections_list } from '../../utils.js';
44
import { SECTIONS_LIST_INTRO, SECTIONS_LIST_OUTRO } from './prompts.js';
5+
import { icons } from '../../icons/index.js';
56

67
export function get_documentation(server: SvelteMcp) {
78
server.tool(
@@ -17,6 +18,7 @@ export function get_documentation(server: SvelteMcp) {
1718
),
1819
),
1920
}),
21+
icons,
2022
},
2123
async ({ section }) => {
2224
let sections: string[];

packages/mcp-server/src/mcp/handlers/tools/list-sections.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import type { SvelteMcp } from '../../index.js';
22
import { format_sections_list } from '../../utils.js';
33
import { SECTIONS_LIST_INTRO, SECTIONS_LIST_OUTRO } from './prompts.js';
4+
import { icons } from '../../icons/index.js';
45

56
export function list_sections(server: SvelteMcp) {
67
server.tool(
78
{
89
name: 'list-sections',
910
description:
1011
'Lists all available Svelte 5 and SvelteKit documentation sections in a structured format. Each section includes a "use_cases" field that describes WHEN this documentation would be useful. You should carefully analyze the use_cases field to determine which sections are relevant for the user\'s query. The use_cases contain comma-separated keywords describing project types (e.g., "e-commerce", "blog"), features (e.g., "authentication", "forms"), components (e.g., "slider", "modal"), development stages (e.g., "deployment", "testing"), or "always" for fundamental concepts. Match these use_cases against the user\'s intent - for example, if building an e-commerce site, fetch sections with use_cases containing "e-commerce", "product listings", "shopping cart", etc. If building a slider, look for "slider", "carousel", "animation", etc. Returns sections as "* title: [section_title], use_cases: [use_cases], path: [file_path]". Always run list-sections FIRST for any Svelte query, then analyze ALL use_cases to identify relevant sections, and finally use get_documentation to fetch ALL relevant sections at once.',
12+
icons,
1113
},
1214
async () => {
1315
const formatted_sections = await format_sections_list();

packages/mcp-server/src/mcp/handlers/tools/playground-link.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { SvelteMcp } from '../../index.js';
22
import * as v from 'valibot';
3+
import { icons } from '../../icons/index.js';
34

45
async function compress_and_encode_text(input: string) {
56
const reader = new Blob([input]).stream().pipeThrough(new CompressionStream('gzip')).getReader();
@@ -54,6 +55,7 @@ export function playground_link(server: SvelteMcp) {
5455
outputSchema: v.object({
5556
url: v.string(),
5657
}),
58+
icons,
5759
},
5860
async ({ files, name, tailwind }) => {
5961
const playground_base = new URL('https://svelte.dev/playground');

packages/mcp-server/src/mcp/handlers/tools/svelte-autofixer.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as v from 'valibot';
44
import { add_compile_issues } from '../../autofixers/add-compile-issues.js';
55
import { add_eslint_issues } from '../../autofixers/add-eslint-issues.js';
66
import { add_autofixers_issues } from '../../autofixers/add-autofixers-issues.js';
7+
import { icons } from '../../icons/index.js';
78

89
export function svelte_autofixer(server: SvelteMcp) {
910
server.tool(
@@ -38,6 +39,7 @@ export function svelte_autofixer(server: SvelteMcp) {
3839
readOnlyHint: true,
3940
openWorldHint: false,
4041
},
42+
icons,
4143
},
4244
async ({
4345
code,
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export const icons = [
2+
{
3+
src: 'https://mcp.svelte.dev/logo.svg',
4+
mimeType: 'image/svg+xml',
5+
},
6+
{
7+
src: 'https://mcp.svelte.dev/logo.png',
8+
mimeType: 'image/png',
9+
},
10+
{
11+
src: 'data:image/png;base64,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',
12+
mimeType: 'image/png',
13+
sizes: ['96x96'],
14+
},
15+
];

packages/mcp-server/src/mcp/index.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,15 @@ import { McpServer } from 'tmcp';
33
import { setup_prompts, setup_resources, setup_tools } from './handlers/index.js';
44
import type { LibSQLDatabase } from 'drizzle-orm/libsql';
55
import type { Schema } from '@sveltejs/mcp-schema';
6+
import { icons } from './icons/index.js';
67

78
export const server = new McpServer(
89
{
910
name: 'Svelte MCP',
1011
version: '0.0.1',
1112
description: 'The official Svelte MCP server implementation',
1213
websiteUrl: 'https://mcp.svelte.dev',
13-
icons: [
14-
{
15-
src: 'https://mcp.svelte.dev/logo.svg',
16-
mimeType: 'image/svg+xml',
17-
},
18-
{
19-
src: 'https://mcp.svelte.dev/logo.png',
20-
mimeType: 'image/png',
21-
},
22-
],
14+
icons,
2315
},
2416
{
2517
adapter: new ValibotJsonSchemaAdapter(),

0 commit comments

Comments
 (0)