Build a local TypeScript server
Create the notes data
Define a small typed dataset that makes every tool result predictable before adding the protocol layer.
Before we touch MCP, let’s decide what data the server is allowed to expose. This is a design decision, not a detail. Everything the server can ever return starts here.
Create src/notes.ts:
export type Note = {
id: string
title: string
tags: string[]
body: string
}
export const notes: Note[] = [
{
id: 'deploy-checklist',
title: 'Deploy checklist',
tags: ['deploy', 'release'],
body: 'Run tests, build the app, then verify the health check.'
},
{
id: 'incident-notes',
title: 'Incident notes',
tags: ['operations'],
body: 'Record the timeline, impact, cause, and follow-up work.'
},
{
id: 'review-guide',
title: 'Review guide',
tags: ['quality'],
body: 'Check behavior, tests, security boundaries, and documentation.'
}
]
This data is deliberately boring. Three notes, no database, no network. Every search returns the same result every time. When something breaks later, we know the problem is in our contract or in the transport, not in a flaky backend.
Notice what’s missing. There is no file path, no database credential, no user ID, no private note. The dataset itself is part of the server’s security boundary. A server can’t leak what it never had.
We’ll expose two views of this data. Search returns summaries: id, title, and tags. Lookup returns the complete note, body included. That split keeps discovery results small without making note IDs unstable.
IDs deserve one more sentence. A stable ID identifies one note for the whole life of the public contract. Titles can change. IDs must not silently point to different content, because a client may have stored them.
Let’s protect that rule with a quick assertion at the bottom of the file:
if (new Set(notes.map(note => note.id)).size !== notes.length) {
throw new Error('Note IDs must be unique')
}
You can run the file on its own to check it:
npx tsx src/notes.ts
It prints nothing. That’s the good outcome. Now try it the other way: copy the first note, paste it as a fourth entry, and run the command again. You get Error: Note IDs must be unique and the process exits. Remove the duplicate before moving on.
Later you can replace this array with a database. Keep the same public schemas and rerun the same tests. That way a backend change never turns into a protocol change.
Lesson completed