@abhishekmcp/notes 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +81 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +147 -0
- package/dist/index.js.map +1 -0
- package/dist/notes.d.ts +36 -0
- package/dist/notes.js +138 -0
- package/dist/notes.js.map +1 -0
- package/package.json +52 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Abhishek
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# @abhishekmcp/notes
|
|
2
|
+
|
|
3
|
+
An [MCP](https://modelcontextprotocol.io) server for managing local markdown notes. Lets any MCP client (Claude Desktop, Claude Code, Cursor, …) search, read, create, link, and organize notes in a folder on your machine.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
**Tools**
|
|
8
|
+
- `list_notes` — list all notes, newest first
|
|
9
|
+
- `read_note` — read a note's contents
|
|
10
|
+
- `create_note` — create a new note (optional overwrite)
|
|
11
|
+
- `append_note` — append to a note (great for journals/logs)
|
|
12
|
+
- `delete_note` — delete a note
|
|
13
|
+
- `search_notes` — full-text search across all notes
|
|
14
|
+
- `get_backlinks` — find notes linking to a note via `[[wiki-link]]` syntax
|
|
15
|
+
|
|
16
|
+
**Resources**
|
|
17
|
+
- Every note is exposed as a `notes://<name>` resource.
|
|
18
|
+
|
|
19
|
+
All file access is sandboxed to the notes directory — paths that try to escape it are rejected.
|
|
20
|
+
|
|
21
|
+
## Install & build
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install
|
|
25
|
+
npm run build
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Configuration
|
|
29
|
+
|
|
30
|
+
Set `NOTES_DIR` to choose where notes live (defaults to `~/notes`):
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
export NOTES_DIR="$HOME/my-notes"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Connecting to a client
|
|
37
|
+
|
|
38
|
+
### Claude Desktop
|
|
39
|
+
|
|
40
|
+
Add to `claude_desktop_config.json`:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"mcpServers": {
|
|
45
|
+
"notes": {
|
|
46
|
+
"command": "node",
|
|
47
|
+
"args": ["/absolute/path/to/mcp-suite/servers/notes/dist/index.js"],
|
|
48
|
+
"env": { "NOTES_DIR": "/absolute/path/to/your/notes" }
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Claude Code
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
claude mcp add notes --env NOTES_DIR=$HOME/notes -- node /absolute/path/to/mcp-suite/servers/notes/dist/index.js
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Publishing to npm
|
|
61
|
+
|
|
62
|
+
This package publishes automatically via GitHub Actions (Trusted Publishing / OIDC) when a
|
|
63
|
+
release tagged `notes-v<version>` is created. See the repo root for the CD workflow.
|
|
64
|
+
|
|
65
|
+
Once published, users can run it without cloning:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"mcpServers": {
|
|
70
|
+
"notes": {
|
|
71
|
+
"command": "npx",
|
|
72
|
+
"args": ["-y", "@abhishekmcp/notes"],
|
|
73
|
+
"env": { "NOTES_DIR": "/path/to/notes" }
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## License
|
|
80
|
+
|
|
81
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
3
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
|
+
import { z } from "zod";
|
|
5
|
+
import { appendNote, createNote, deleteNote, ensureNotesDir, getBacklinks, getNotesDir, listNotes, readNote, searchNotes, } from "./notes.js";
|
|
6
|
+
const server = new McpServer({
|
|
7
|
+
name: "mcp-notes-server",
|
|
8
|
+
version: "0.1.0",
|
|
9
|
+
});
|
|
10
|
+
// A small helper to wrap a string into the MCP text-content shape.
|
|
11
|
+
const text = (value) => ({
|
|
12
|
+
content: [{ type: "text", text: value }],
|
|
13
|
+
});
|
|
14
|
+
// --- Tools ---------------------------------------------------------------
|
|
15
|
+
server.registerTool("list_notes", {
|
|
16
|
+
title: "List notes",
|
|
17
|
+
description: "List all markdown notes in the notes directory, newest first. " +
|
|
18
|
+
"Returns each note's name, size, and last-modified time.",
|
|
19
|
+
inputSchema: {},
|
|
20
|
+
}, async () => {
|
|
21
|
+
const notes = await listNotes();
|
|
22
|
+
if (notes.length === 0)
|
|
23
|
+
return text("No notes found.");
|
|
24
|
+
const lines = notes.map((n) => `- ${n.name} (${n.size} bytes, modified ${n.modified})`);
|
|
25
|
+
return text(`Found ${notes.length} note(s):\n${lines.join("\n")}`);
|
|
26
|
+
});
|
|
27
|
+
server.registerTool("read_note", {
|
|
28
|
+
title: "Read a note",
|
|
29
|
+
description: "Read the full contents of a note by name (extension optional).",
|
|
30
|
+
inputSchema: {
|
|
31
|
+
name: z.string().describe("Note name, e.g. 'ideas' or 'projects/mcp'"),
|
|
32
|
+
},
|
|
33
|
+
}, async ({ name }) => {
|
|
34
|
+
try {
|
|
35
|
+
return text(await readNote(name));
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
return text(`Could not read note "${name}". Does it exist?`);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
server.registerTool("create_note", {
|
|
42
|
+
title: "Create a note",
|
|
43
|
+
description: "Create a new markdown note. Fails if it already exists unless overwrite is true.",
|
|
44
|
+
inputSchema: {
|
|
45
|
+
name: z.string().describe("Note name, e.g. 'ideas' or 'projects/mcp'"),
|
|
46
|
+
content: z.string().describe("Markdown content of the note"),
|
|
47
|
+
overwrite: z
|
|
48
|
+
.boolean()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe("Overwrite an existing note (default false)"),
|
|
51
|
+
},
|
|
52
|
+
}, async ({ name, content, overwrite }) => {
|
|
53
|
+
try {
|
|
54
|
+
const file = await createNote(name, content, overwrite ?? false);
|
|
55
|
+
return text(`Created note at ${file}`);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
return text(`Failed to create note: ${err.message}`);
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
server.registerTool("append_note", {
|
|
62
|
+
title: "Append to a note",
|
|
63
|
+
description: "Append content to an existing note (creates it if missing). " +
|
|
64
|
+
"Useful for journals, logs, and running lists.",
|
|
65
|
+
inputSchema: {
|
|
66
|
+
name: z.string().describe("Note name"),
|
|
67
|
+
content: z.string().describe("Markdown content to append"),
|
|
68
|
+
},
|
|
69
|
+
}, async ({ name, content }) => {
|
|
70
|
+
const file = await appendNote(name, content);
|
|
71
|
+
return text(`Appended to ${file}`);
|
|
72
|
+
});
|
|
73
|
+
server.registerTool("delete_note", {
|
|
74
|
+
title: "Delete a note",
|
|
75
|
+
description: "Permanently delete a note by name.",
|
|
76
|
+
inputSchema: {
|
|
77
|
+
name: z.string().describe("Note name to delete"),
|
|
78
|
+
},
|
|
79
|
+
annotations: { destructiveHint: true },
|
|
80
|
+
}, async ({ name }) => {
|
|
81
|
+
try {
|
|
82
|
+
await deleteNote(name);
|
|
83
|
+
return text(`Deleted note "${name}".`);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return text(`Could not delete note "${name}". Does it exist?`);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
server.registerTool("search_notes", {
|
|
90
|
+
title: "Search notes",
|
|
91
|
+
description: "Case-insensitive full-text search across all notes. " +
|
|
92
|
+
"Returns matching lines with their note name and line number.",
|
|
93
|
+
inputSchema: {
|
|
94
|
+
query: z.string().describe("Text to search for"),
|
|
95
|
+
limit: z
|
|
96
|
+
.number()
|
|
97
|
+
.int()
|
|
98
|
+
.positive()
|
|
99
|
+
.optional()
|
|
100
|
+
.describe("Max number of matches (default 50)"),
|
|
101
|
+
},
|
|
102
|
+
}, async ({ query, limit }) => {
|
|
103
|
+
const hits = await searchNotes(query, limit ?? 50);
|
|
104
|
+
if (hits.length === 0)
|
|
105
|
+
return text(`No matches for "${query}".`);
|
|
106
|
+
const lines = hits.map((h) => `${h.name}:${h.line}: ${h.text}`);
|
|
107
|
+
return text(`${hits.length} match(es):\n${lines.join("\n")}`);
|
|
108
|
+
});
|
|
109
|
+
server.registerTool("get_backlinks", {
|
|
110
|
+
title: "Get backlinks",
|
|
111
|
+
description: "Find all notes that link to the given note using [[wiki-link]] syntax.",
|
|
112
|
+
inputSchema: {
|
|
113
|
+
name: z.string().describe("The note to find backlinks for"),
|
|
114
|
+
},
|
|
115
|
+
}, async ({ name }) => {
|
|
116
|
+
const hits = await getBacklinks(name);
|
|
117
|
+
if (hits.length === 0)
|
|
118
|
+
return text(`No notes link to "${name}".`);
|
|
119
|
+
const lines = hits.map((h) => `${h.name}:${h.line}: ${h.text}`);
|
|
120
|
+
return text(`${hits.length} backlink(s) to "${name}":\n${lines.join("\n")}`);
|
|
121
|
+
});
|
|
122
|
+
// --- Resources -----------------------------------------------------------
|
|
123
|
+
// Expose every note as a readable resource via a notes:// URI scheme.
|
|
124
|
+
server.registerResource("note", "notes://{name}", {
|
|
125
|
+
title: "Note",
|
|
126
|
+
description: "A markdown note, addressable by name.",
|
|
127
|
+
mimeType: "text/markdown",
|
|
128
|
+
}, async (uri) => {
|
|
129
|
+
const name = decodeURIComponent(uri.pathname.replace(/^\/+/, "") || uri.href.replace("notes://", ""));
|
|
130
|
+
const content = await readNote(name);
|
|
131
|
+
return {
|
|
132
|
+
contents: [{ uri: uri.href, mimeType: "text/markdown", text: content }],
|
|
133
|
+
};
|
|
134
|
+
});
|
|
135
|
+
// --- Startup -------------------------------------------------------------
|
|
136
|
+
async function main() {
|
|
137
|
+
await ensureNotesDir();
|
|
138
|
+
const transport = new StdioServerTransport();
|
|
139
|
+
await server.connect(transport);
|
|
140
|
+
// Log to stderr — stdout is reserved for the MCP protocol.
|
|
141
|
+
console.error(`mcp-notes-server running. Notes dir: ${getNotesDir()}`);
|
|
142
|
+
}
|
|
143
|
+
main().catch((err) => {
|
|
144
|
+
console.error("Fatal error starting mcp-notes-server:", err);
|
|
145
|
+
process.exit(1);
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/notes.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the notes directory from the NOTES_DIR env var, defaulting to ~/notes.
|
|
3
|
+
* A leading "~" is expanded to the user's home directory.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getNotesDir(): string;
|
|
6
|
+
/** Ensure the notes directory exists. */
|
|
7
|
+
export declare function ensureNotesDir(): Promise<string>;
|
|
8
|
+
/**
|
|
9
|
+
* Turn a user-supplied note name into a safe absolute path inside the notes
|
|
10
|
+
* directory. Throws if the resolved path would escape the notes directory.
|
|
11
|
+
* A ".md" extension is added when missing.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveNotePath(name: string): string;
|
|
14
|
+
export interface NoteInfo {
|
|
15
|
+
name: string;
|
|
16
|
+
size: number;
|
|
17
|
+
modified: string;
|
|
18
|
+
}
|
|
19
|
+
/** Recursively list all markdown notes in the notes directory. */
|
|
20
|
+
export declare function listNotes(): Promise<NoteInfo[]>;
|
|
21
|
+
export declare function readNote(name: string): Promise<string>;
|
|
22
|
+
export declare function createNote(name: string, content: string, overwrite?: boolean): Promise<string>;
|
|
23
|
+
export declare function appendNote(name: string, content: string): Promise<string>;
|
|
24
|
+
export declare function deleteNote(name: string): Promise<void>;
|
|
25
|
+
export interface SearchHit {
|
|
26
|
+
name: string;
|
|
27
|
+
line: number;
|
|
28
|
+
text: string;
|
|
29
|
+
}
|
|
30
|
+
/** Case-insensitive substring search across all notes. */
|
|
31
|
+
export declare function searchNotes(query: string, limit?: number): Promise<SearchHit[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Find notes that link to the given note via [[wiki-link]] syntax.
|
|
34
|
+
* Matches the bare note name (with or without the .md extension).
|
|
35
|
+
*/
|
|
36
|
+
export declare function getBacklinks(name: string): Promise<SearchHit[]>;
|
package/dist/notes.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { promises as fs } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the notes directory from the NOTES_DIR env var, defaulting to ~/notes.
|
|
6
|
+
* A leading "~" is expanded to the user's home directory.
|
|
7
|
+
*/
|
|
8
|
+
export function getNotesDir() {
|
|
9
|
+
const raw = process.env.NOTES_DIR ?? path.join(homedir(), "notes");
|
|
10
|
+
const expanded = raw.startsWith("~")
|
|
11
|
+
? path.join(homedir(), raw.slice(1))
|
|
12
|
+
: raw;
|
|
13
|
+
return path.resolve(expanded);
|
|
14
|
+
}
|
|
15
|
+
/** Ensure the notes directory exists. */
|
|
16
|
+
export async function ensureNotesDir() {
|
|
17
|
+
const dir = getNotesDir();
|
|
18
|
+
await fs.mkdir(dir, { recursive: true });
|
|
19
|
+
return dir;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Turn a user-supplied note name into a safe absolute path inside the notes
|
|
23
|
+
* directory. Throws if the resolved path would escape the notes directory.
|
|
24
|
+
* A ".md" extension is added when missing.
|
|
25
|
+
*/
|
|
26
|
+
export function resolveNotePath(name) {
|
|
27
|
+
const dir = getNotesDir();
|
|
28
|
+
const withExt = name.endsWith(".md") ? name : `${name}.md`;
|
|
29
|
+
const resolved = path.resolve(dir, withExt);
|
|
30
|
+
const rel = path.relative(dir, resolved);
|
|
31
|
+
if (rel.startsWith("..") || path.isAbsolute(rel)) {
|
|
32
|
+
throw new Error(`Refusing to access "${name}": path escapes the notes directory.`);
|
|
33
|
+
}
|
|
34
|
+
return resolved;
|
|
35
|
+
}
|
|
36
|
+
/** Recursively list all markdown notes in the notes directory. */
|
|
37
|
+
export async function listNotes() {
|
|
38
|
+
const dir = await ensureNotesDir();
|
|
39
|
+
const results = [];
|
|
40
|
+
async function walk(current) {
|
|
41
|
+
const entries = await fs.readdir(current, { withFileTypes: true });
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
const full = path.join(current, entry.name);
|
|
44
|
+
if (entry.isDirectory()) {
|
|
45
|
+
await walk(full);
|
|
46
|
+
}
|
|
47
|
+
else if (entry.isFile() && entry.name.endsWith(".md")) {
|
|
48
|
+
const stat = await fs.stat(full);
|
|
49
|
+
const rel = path.relative(dir, full).replace(/\.md$/, "");
|
|
50
|
+
results.push({
|
|
51
|
+
name: rel,
|
|
52
|
+
size: stat.size,
|
|
53
|
+
modified: stat.mtime.toISOString(),
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
await walk(dir);
|
|
59
|
+
results.sort((a, b) => b.modified.localeCompare(a.modified));
|
|
60
|
+
return results;
|
|
61
|
+
}
|
|
62
|
+
export async function readNote(name) {
|
|
63
|
+
const file = resolveNotePath(name);
|
|
64
|
+
return fs.readFile(file, "utf8");
|
|
65
|
+
}
|
|
66
|
+
export async function createNote(name, content, overwrite = false) {
|
|
67
|
+
const file = resolveNotePath(name);
|
|
68
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
69
|
+
if (!overwrite) {
|
|
70
|
+
try {
|
|
71
|
+
await fs.access(file);
|
|
72
|
+
throw new Error(`Note "${name}" already exists. Use overwrite or append instead.`);
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
// ENOENT means it does not exist yet — that's what we want.
|
|
76
|
+
if (err.code !== "ENOENT")
|
|
77
|
+
throw err;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
await fs.writeFile(file, content, "utf8");
|
|
81
|
+
return file;
|
|
82
|
+
}
|
|
83
|
+
export async function appendNote(name, content) {
|
|
84
|
+
const file = resolveNotePath(name);
|
|
85
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
86
|
+
// Separate appended content with a blank line for readability.
|
|
87
|
+
const prefix = content.startsWith("\n") ? "" : "\n\n";
|
|
88
|
+
await fs.appendFile(file, prefix + content, "utf8");
|
|
89
|
+
return file;
|
|
90
|
+
}
|
|
91
|
+
export async function deleteNote(name) {
|
|
92
|
+
const file = resolveNotePath(name);
|
|
93
|
+
await fs.unlink(file);
|
|
94
|
+
}
|
|
95
|
+
/** Case-insensitive substring search across all notes. */
|
|
96
|
+
export async function searchNotes(query, limit = 50) {
|
|
97
|
+
const notes = await listNotes();
|
|
98
|
+
const needle = query.toLowerCase();
|
|
99
|
+
const hits = [];
|
|
100
|
+
for (const note of notes) {
|
|
101
|
+
const content = await readNote(note.name);
|
|
102
|
+
const lines = content.split("\n");
|
|
103
|
+
for (let i = 0; i < lines.length; i++) {
|
|
104
|
+
if (lines[i].toLowerCase().includes(needle)) {
|
|
105
|
+
hits.push({ name: note.name, line: i + 1, text: lines[i].trim() });
|
|
106
|
+
if (hits.length >= limit)
|
|
107
|
+
return hits;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return hits;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Find notes that link to the given note via [[wiki-link]] syntax.
|
|
115
|
+
* Matches the bare note name (with or without the .md extension).
|
|
116
|
+
*/
|
|
117
|
+
export async function getBacklinks(name) {
|
|
118
|
+
const target = name.replace(/\.md$/, "");
|
|
119
|
+
const notes = await listNotes();
|
|
120
|
+
const hits = [];
|
|
121
|
+
for (const note of notes) {
|
|
122
|
+
if (note.name === target)
|
|
123
|
+
continue;
|
|
124
|
+
const content = await readNote(note.name);
|
|
125
|
+
const lines = content.split("\n");
|
|
126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
127
|
+
const wikiLinks = lines[i].match(/\[\[([^\]]+)\]\]/g) ?? [];
|
|
128
|
+
for (const link of wikiLinks) {
|
|
129
|
+
const inner = link.slice(2, -2).split("|")[0].trim().replace(/\.md$/, "");
|
|
130
|
+
if (inner === target) {
|
|
131
|
+
hits.push({ name: note.name, line: i + 1, text: lines[i].trim() });
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return hits;
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notes.js","sourceRoot":"","sources":["../src/notes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;GAGG;AACH,MAAM,UAAU,WAAW;IACzB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC;QAClC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACpC,CAAC,CAAC,GAAG,CAAC;IACR,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC;AAED,yCAAyC;AACzC,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACzC,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,MAAM,GAAG,GAAG,WAAW,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAE5C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACzC,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CACb,uBAAuB,IAAI,sCAAsC,CAClE,CAAC;IACJ,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,GAAG,GAAG,MAAM,cAAc,EAAE,CAAC;IACnC,MAAM,OAAO,GAAe,EAAE,CAAC;IAE/B,KAAK,UAAU,IAAI,CAAC,OAAe;QACjC,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5C,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;gBACxB,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,CAAC;iBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxD,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBACjC,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC1D,OAAO,CAAC,IAAI,CAAC;oBACX,IAAI,EAAE,GAAG;oBACT,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;iBACnC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC7D,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,OAAO,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,OAAe,EACf,SAAS,GAAG,KAAK;IAEjB,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAExD,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACtB,MAAM,IAAI,KAAK,CACb,SAAS,IAAI,oDAAoD,CAClE,CAAC;QACJ,CAAC;QAAC,OAAO,GAAY,EAAE,CAAC;YACtB,4DAA4D;YAC5D,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ;gBAAE,MAAM,GAAG,CAAC;QAClE,CAAC;IACH,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAY,EACZ,OAAe;IAEf,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxD,+DAA+D;IAC/D,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACtD,MAAM,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC,CAAC;IACpD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY;IAC3C,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAQD,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAa,EACb,KAAK,GAAG,EAAE;IAEV,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IACnC,MAAM,IAAI,GAAgB,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACnE,IAAI,IAAI,CAAC,MAAM,IAAI,KAAK;oBAAE,OAAO,IAAI,CAAC;YACxC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACzC,MAAM,KAAK,GAAG,MAAM,SAAS,EAAE,CAAC;IAChC,MAAM,IAAI,GAAgB,EAAE,CAAC;IAE7B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM;YAAE,SAAS;QACnC,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,IAAI,EAAE,CAAC;YAC5D,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;gBAC1E,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;oBACrB,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;gBACrE,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@abhishekmcp/notes",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "MCP server for local markdown notes — search, create, link, and read notes from any MCP client.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"mcp-notes": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"publishConfig": {
|
|
13
|
+
"access": "public",
|
|
14
|
+
"provenance": true
|
|
15
|
+
},
|
|
16
|
+
"scripts": {
|
|
17
|
+
"build": "tsc",
|
|
18
|
+
"watch": "tsc --watch",
|
|
19
|
+
"start": "node dist/index.js",
|
|
20
|
+
"dev": "tsc && node dist/index.js",
|
|
21
|
+
"prepublishOnly": "npm run build"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mcp",
|
|
25
|
+
"modelcontextprotocol",
|
|
26
|
+
"notes",
|
|
27
|
+
"markdown",
|
|
28
|
+
"claude"
|
|
29
|
+
],
|
|
30
|
+
"author": "Abhishek (https://github.com/Abhishekkumar2021)",
|
|
31
|
+
"license": "MIT",
|
|
32
|
+
"homepage": "https://github.com/Abhishekkumar2021/mcp-suite/tree/main/servers/notes#readme",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/Abhishekkumar2021/mcp-suite.git",
|
|
36
|
+
"directory": "servers/notes"
|
|
37
|
+
},
|
|
38
|
+
"bugs": {
|
|
39
|
+
"url": "https://github.com/Abhishekkumar2021/mcp-suite/issues"
|
|
40
|
+
},
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
46
|
+
"zod": "^3.23.8"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/node": "^22.0.0",
|
|
50
|
+
"typescript": "^5.6.0"
|
|
51
|
+
}
|
|
52
|
+
}
|