Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.

Commit d8a8c6e

Browse files
committed
Refactor/expand into a more substantial example
1 parent b9fd2fb commit d8a8c6e

File tree

1 file changed

+112
-16
lines changed

1 file changed

+112
-16
lines changed

template/src/index.ts.ejs

Lines changed: 112 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,38 @@
1-
#!/usr/bin/env node
1+
/**
2+
* This is a template MCP server that implements a simple notes system.
3+
* It demonstrates core MCP concepts like resources and tools by allowing:
4+
* - Listing notes as resources
5+
* - Reading individual notes
6+
* - Creating new notes via a tool
7+
*/
28

39
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
410
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
511
import {
12+
CallToolRequestSchema,
613
ListResourcesRequestSchema,
714
ListToolsRequestSchema,
15+
ReadResourceRequestSchema,
816
} from "@modelcontextprotocol/sdk/types.js";
917

18+
/**
19+
* Type alias for a note object.
20+
*/
21+
type Note = { title: string, content: string };
22+
23+
/**
24+
* Simple in-memory storage for notes.
25+
* In a real implementation, this would likely be backed by a database.
26+
*/
27+
const notes: { [id: string]: Note } = {
28+
"1": { title: "First Note", content: "This is note 1" },
29+
"2": { title: "Second Note", content: "This is note 2" }
30+
};
31+
32+
/**
33+
* Create an MCP server with capabilities for resources (to list/read notes)
34+
* and tools (to create new notes).
35+
*/
1036
const server = new Server(
1137
{
1238
name: "<%= name %>",
@@ -17,41 +43,111 @@ const server = new Server(
1743
resources: {},
1844
tools: {},
1945
},
20-
},
46+
}
2147
);
2248

49+
/**
50+
* Handler for listing available notes as resources.
51+
* Each note is exposed as a resource with:
52+
* - A note:// URI scheme
53+
* - Plain text MIME type
54+
* - Human readable name and description (now including the note title)
55+
*/
2356
server.setRequestHandler(ListResourcesRequestSchema, async () => {
2457
return {
25-
resources: [
26-
{
27-
uri: "example://hello",
28-
mimeType: "text/plain",
29-
name: "Example resource",
30-
},
31-
],
58+
resources: Object.entries(notes).map(([id, note]) => ({
59+
uri: `note:///${id}`,
60+
mimeType: "text/plain",
61+
name: note.title,
62+
description: `A text note: ${note.title}`
63+
}))
64+
};
65+
});
66+
67+
/**
68+
* Handler for reading the contents of a specific note.
69+
* Takes a note:// URI and returns the note content as plain text.
70+
*/
71+
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
72+
const url = new URL(request.params.uri);
73+
const id = url.pathname.replace(/^\//, '');
74+
const note = notes[id];
75+
76+
if (!note) {
77+
throw new Error(`Note ${id} not found`);
78+
}
79+
80+
return {
81+
contents: [{
82+
uri: request.params.uri,
83+
mimeType: "text/plain",
84+
text: note.content
85+
}]
3286
};
3387
});
3488

89+
/**
90+
* Handler that lists available tools.
91+
* Exposes a single "create_note" tool that lets clients create new notes.
92+
*/
3593
server.setRequestHandler(ListToolsRequestSchema, async () => {
3694
return {
3795
tools: [
3896
{
39-
name: "example",
40-
description: "An example tool",
97+
name: "create_note",
98+
description: "Create a new note",
4199
inputSchema: {
42100
type: "object",
43101
properties: {
44-
message: {
102+
title: {
45103
type: "string",
46-
description: "Message to echo",
104+
description: "Title of the note"
47105
},
106+
content: {
107+
type: "string",
108+
description: "Text content of the note"
109+
}
48110
},
49-
},
50-
},
51-
],
111+
required: ["title", "content"]
112+
}
113+
}
114+
]
52115
};
53116
});
54117

118+
/**
119+
* Handler for the create_note tool.
120+
* Creates a new note with the provided title and content, and returns success message.
121+
*/
122+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
123+
switch (request.params.name) {
124+
case "create_note": {
125+
const title = String(request.params.arguments?.title);
126+
const content = String(request.params.arguments?.content);
127+
if (!title || !content) {
128+
throw new Error("Title and content are required");
129+
}
130+
131+
const id = String(Object.keys(notes).length + 1);
132+
notes[id] = { title, content };
133+
134+
return {
135+
content: [{
136+
type: "text",
137+
text: `Created note ${id}: ${title}`
138+
}]
139+
};
140+
}
141+
142+
default:
143+
throw new Error("Unknown tool");
144+
}
145+
});
146+
147+
/**
148+
* Start the server using stdio transport.
149+
* This allows the server to communicate via standard input/output streams.
150+
*/
55151
async function main() {
56152
const transport = new StdioServerTransport();
57153
await server.connect(transport);

0 commit comments

Comments
 (0)