-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathindex.ts
More file actions
144 lines (131 loc) · 4.39 KB
/
index.ts
File metadata and controls
144 lines (131 loc) · 4.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
import { timerHtml, display_factHtml, conversionHtml } from "./generated/html.js";
import { createTemplatedUIResource } from "./utils/html-template.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
// @ts-ignore idk what's going on but it works and it's simple
import { createUIResource } from "@mcp-ui/server";
export default function createServer() {
const server = new McpServer({
name: "widget-mcp",
version: "1.0.0",
});
server.registerTool(
"timer",
{
title: "Timer",
description:
"Start a timer. You don't need to say anything else after answering with this tool.",
inputSchema: {
duration: z.number().describe("The duration of the timer in seconds"),
},
},
async ({ duration }) => {
const timerResource = createTemplatedUIResource(
createUIResource,
"ui://widget/timer",
timerHtml,
{ duration, mode: "timer" }
);
return {
content: [timerResource],
};
}
);
server.registerTool(
"stopwatch",
{
title: "Stopwatch",
description:
"Start a stopwatch that counts up from zero. You don't need to say anything else after answering with this tool.",
inputSchema: {},
},
async () => {
const stopwatchResource = createTemplatedUIResource(
createUIResource,
"ui://widget/stopwatch",
timerHtml,
{ mode: "stopwatch" }
);
return {
content: [stopwatchResource],
};
}
);
server.registerTool(
"display-fact",
{
title: "Display Fact",
description:
"Display a simple fact. Should be used when answering a users question that has a short factual answer. You don't need to say anything else after answering with this tool. Example: { description: 'The capital of France', fact: 'Paris' }",
inputSchema: {
description: z.string().describe("A description of the fact"),
fact: z.string().describe("The fact to display. Should be short and concise."),
},
},
async ({ description, fact }) => {
const factResource = createTemplatedUIResource(
createUIResource,
"ui://widget/display-fact",
display_factHtml,
{ description, fact }
);
return {
content: [factResource],
};
}
);
server.registerTool(
"conversion",
{
title: "Unit Conversion",
description:
"Display a unit conversion widget that allows real-time conversion between multiple units. Each unit should contain a formula for each other unit in terms of the current unit. Example input: { units: [{id: 'ft', name: 'Feet', formulas: {in:'{ft} * 12'}, {id: 'in', name: 'Inches', formulas: {ft:'{in} * 12'}}], initialValue: { id: 'ft', value: 1 }}. You don't need to say anything else after answering with this tool.",
inputSchema: {
units: z
.array(
z.object({
id: z.string().describe("Unique identifier for the unit"),
name: z.string().describe("Display name for the unit"),
formulas: z
.record(z.string())
.describe("Conversion formulas to other units, using {id} as placeholder."),
})
)
.describe("Array of units with conversion formulas"),
initialValue: z
.object({
id: z.string().describe("ID of the unit to set initial value for"),
value: z.number().describe("Initial value for the unit"),
})
.describe("Initial value to display in the converter"),
},
},
async ({ units, initialValue }) => {
const conversionResource = createTemplatedUIResource(
createUIResource,
"ui://widget/conversion",
conversionHtml,
{ units, initialValue }
);
return {
content: [conversionResource],
};
}
);
return server.server;
}
async function runServer() {
const server = createServer();
const transport = new StdioServerTransport();
await server.connect(transport);
process.on("SIGINT", async () => {
await server.close();
process.exit(0);
});
console.error("MCP Starter Server running on stdio");
}
runServer().catch((error) => {
console.error("Fatal error running server:", error);
process.exit(1);
});