stickyrice-mcp 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 +156 -0
- package/dist/auth.d.ts +4 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +112 -0
- package/dist/auth.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +40 -0
- package/dist/config.js.map +1 -0
- package/dist/convex-client.d.ts +18 -0
- package/dist/convex-client.d.ts.map +1 -0
- package/dist/convex-client.js +73 -0
- package/dist/convex-client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +79 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/index.d.ts +11 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +73 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/server.d.ts +5 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +46 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/boards.d.ts +5 -0
- package/dist/tools/boards.d.ts.map +1 -0
- package/dist/tools/boards.js +156 -0
- package/dist/tools/boards.js.map +1 -0
- package/dist/tools/columns.d.ts +5 -0
- package/dist/tools/columns.d.ts.map +1 -0
- package/dist/tools/columns.js +101 -0
- package/dist/tools/columns.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +55 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/note-items.d.ts +5 -0
- package/dist/tools/note-items.d.ts.map +1 -0
- package/dist/tools/note-items.js +99 -0
- package/dist/tools/note-items.js.map +1 -0
- package/dist/tools/notes.d.ts +5 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +227 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/tags.d.ts +5 -0
- package/dist/tools/tags.d.ts.map +1 -0
- package/dist/tools/tags.js +99 -0
- package/dist/tools/tags.js.map +1 -0
- package/dist/tools/workspaces.d.ts +5 -0
- package/dist/tools/workspaces.d.ts.map +1 -0
- package/dist/tools/workspaces.js +96 -0
- package/dist/tools/workspaces.js.map +1 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Sticky Rice
|
|
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,156 @@
|
|
|
1
|
+
# stickyrice-mcp
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for [Sticky Rice](https://stickyrice.app) - interact with your notes from Claude.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
### 1. Authenticate
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx stickyrice-mcp auth
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
This opens your browser to authorize the connection. Once approved, your credentials are saved locally.
|
|
14
|
+
|
|
15
|
+
### 2. Configure Claude
|
|
16
|
+
|
|
17
|
+
Add to your Claude config (`~/.claude.json` or Claude Desktop settings):
|
|
18
|
+
|
|
19
|
+
```json
|
|
20
|
+
{
|
|
21
|
+
"mcpServers": {
|
|
22
|
+
"stickyrice": {
|
|
23
|
+
"command": "npx",
|
|
24
|
+
"args": ["-y", "stickyrice-mcp"]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 3. Restart Claude
|
|
31
|
+
|
|
32
|
+
You're done! Ask Claude about your notes.
|
|
33
|
+
|
|
34
|
+
## Commands
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npx stickyrice-mcp auth # Authenticate (opens browser)
|
|
38
|
+
npx stickyrice-mcp logout # Remove saved credentials
|
|
39
|
+
npx stickyrice-mcp status # Check authentication status
|
|
40
|
+
npx stickyrice-mcp help # Show help
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Available Tools
|
|
44
|
+
|
|
45
|
+
### Workspaces
|
|
46
|
+
| Tool | Description |
|
|
47
|
+
|------|-------------|
|
|
48
|
+
| `list_workspaces` | List all your workspaces |
|
|
49
|
+
| `create_workspace` | Create a new workspace |
|
|
50
|
+
| `update_workspace` | Update workspace name or order |
|
|
51
|
+
| `delete_workspace` | Delete a workspace (moves boards to Personal) |
|
|
52
|
+
|
|
53
|
+
### Boards
|
|
54
|
+
| Tool | Description |
|
|
55
|
+
|------|-------------|
|
|
56
|
+
| `list_boards` | List all your boards |
|
|
57
|
+
| `get_board` | Get a board with all columns, notes, and items |
|
|
58
|
+
| `create_board` | Create a new board |
|
|
59
|
+
| `update_board` | Update board title, order, or move to workspace |
|
|
60
|
+
| `delete_board` | Delete a board and all its contents |
|
|
61
|
+
| `search_notes` | Search notes by keyword across all boards |
|
|
62
|
+
|
|
63
|
+
### Columns
|
|
64
|
+
| Tool | Description |
|
|
65
|
+
|------|-------------|
|
|
66
|
+
| `create_column` | Create a new column in a board |
|
|
67
|
+
| `update_column` | Update column title, order, or move to another board |
|
|
68
|
+
| `delete_column` | Delete a column and all its notes |
|
|
69
|
+
|
|
70
|
+
### Notes
|
|
71
|
+
| Tool | Description |
|
|
72
|
+
|------|-------------|
|
|
73
|
+
| `create_note` | Create a new note in a column |
|
|
74
|
+
| `update_note` | Update note title, color, or move to another column |
|
|
75
|
+
| `delete_note` | Delete a note and all its items |
|
|
76
|
+
| `get_note` | Get a single note with all details |
|
|
77
|
+
|
|
78
|
+
### Note Items
|
|
79
|
+
| Tool | Description |
|
|
80
|
+
|------|-------------|
|
|
81
|
+
| `add_note_item` | Add a bullet journal item to a note |
|
|
82
|
+
| `update_note_item` | Update item content or type (todo, doing, done, etc.) |
|
|
83
|
+
| `delete_note_item` | Remove an item from a note |
|
|
84
|
+
|
|
85
|
+
### Tags
|
|
86
|
+
| Tool | Description |
|
|
87
|
+
|------|-------------|
|
|
88
|
+
| `list_tags` | List all your tags |
|
|
89
|
+
| `create_tag` | Create a new tag |
|
|
90
|
+
| `tag_note` | Apply a tag to a note |
|
|
91
|
+
| `untag_note` | Remove a tag from a note |
|
|
92
|
+
|
|
93
|
+
## Available Resources
|
|
94
|
+
|
|
95
|
+
| Resource | Description |
|
|
96
|
+
|----------|-------------|
|
|
97
|
+
| `stickyrice://boards` | All boards |
|
|
98
|
+
| `stickyrice://board/{id}` | Full board with notes |
|
|
99
|
+
| `stickyrice://note/{id}` | Single note details |
|
|
100
|
+
| `stickyrice://tags` | All tags |
|
|
101
|
+
| `stickyrice://todos` | All incomplete todos |
|
|
102
|
+
|
|
103
|
+
## Examples
|
|
104
|
+
|
|
105
|
+
Ask Claude things like:
|
|
106
|
+
|
|
107
|
+
**Workspaces & Organization:**
|
|
108
|
+
- "Create a new workspace called 'Projects'"
|
|
109
|
+
- "Show me all my workspaces"
|
|
110
|
+
- "Create a new board called 'Q1 Goals' in my Projects workspace"
|
|
111
|
+
|
|
112
|
+
**Boards & Columns:**
|
|
113
|
+
- "Show me all my boards"
|
|
114
|
+
- "Create a column called 'In Progress' in my Work board"
|
|
115
|
+
- "What's on my Growth Plan board?"
|
|
116
|
+
|
|
117
|
+
**Notes & Items:**
|
|
118
|
+
- "Create a new note in my Ideas column with title 'MCP Integration'"
|
|
119
|
+
- "Add a todo item 'Review PR' to my Tasks note"
|
|
120
|
+
- "Mark the first todo in my Tasks note as done"
|
|
121
|
+
- "Delete the Mobile App note from my Product column"
|
|
122
|
+
|
|
123
|
+
**Search & Tags:**
|
|
124
|
+
- "Search my notes for 'meeting'"
|
|
125
|
+
- "Tag my Project note with 'urgent'"
|
|
126
|
+
|
|
127
|
+
## Manual Authentication
|
|
128
|
+
|
|
129
|
+
If you prefer not to use browser auth, you can set environment variables:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"mcpServers": {
|
|
134
|
+
"stickyrice": {
|
|
135
|
+
"command": "npx",
|
|
136
|
+
"args": ["-y", "stickyrice-mcp"],
|
|
137
|
+
"env": {
|
|
138
|
+
"CONVEX_URL": "https://glad-dragon-481.convex.cloud",
|
|
139
|
+
"STICKYRICE_API_KEY": "sr_your_api_key"
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Get your API key from Sticky Rice Settings.
|
|
147
|
+
|
|
148
|
+
## Requirements
|
|
149
|
+
|
|
150
|
+
- Node.js 18 or higher
|
|
151
|
+
- A Sticky Rice account
|
|
152
|
+
- Claude Desktop or Claude Code
|
|
153
|
+
|
|
154
|
+
## License
|
|
155
|
+
|
|
156
|
+
MIT
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AA0EA,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAqDlD;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAS5C;AAED,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAY5C"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { writeConfig, DEFAULT_CONVEX_URL, readConfig, deleteConfig, getConfigPath } from "./config.js";
|
|
2
|
+
const POLL_INTERVAL = 2000; // 2 seconds
|
|
3
|
+
const MAX_POLL_TIME = 10 * 60 * 1000; // 10 minutes
|
|
4
|
+
async function requestDeviceCode(httpUrl) {
|
|
5
|
+
const response = await fetch(`${httpUrl}/mcp/device`, {
|
|
6
|
+
method: "POST",
|
|
7
|
+
headers: { "Content-Type": "application/json" },
|
|
8
|
+
});
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
throw new Error("Failed to request device code");
|
|
11
|
+
}
|
|
12
|
+
return response.json();
|
|
13
|
+
}
|
|
14
|
+
async function pollForToken(httpUrl, userCode) {
|
|
15
|
+
const startTime = Date.now();
|
|
16
|
+
while (Date.now() - startTime < MAX_POLL_TIME) {
|
|
17
|
+
const response = await fetch(`${httpUrl}/mcp/token`, {
|
|
18
|
+
method: "POST",
|
|
19
|
+
headers: { "Content-Type": "application/json" },
|
|
20
|
+
body: JSON.stringify({ userCode }),
|
|
21
|
+
});
|
|
22
|
+
const data = (await response.json());
|
|
23
|
+
if (data.status === "approved" && data.apiKey) {
|
|
24
|
+
return data.apiKey;
|
|
25
|
+
}
|
|
26
|
+
if (data.error && data.error !== "authorization_pending") {
|
|
27
|
+
throw new Error(data.error);
|
|
28
|
+
}
|
|
29
|
+
// Wait before polling again
|
|
30
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
|
|
31
|
+
}
|
|
32
|
+
throw new Error("Authorization timed out");
|
|
33
|
+
}
|
|
34
|
+
async function openBrowser(url) {
|
|
35
|
+
const { platform } = process;
|
|
36
|
+
let command;
|
|
37
|
+
if (platform === "darwin") {
|
|
38
|
+
command = "open";
|
|
39
|
+
}
|
|
40
|
+
else if (platform === "win32") {
|
|
41
|
+
command = "start";
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
command = "xdg-open";
|
|
45
|
+
}
|
|
46
|
+
const { exec } = await import("child_process");
|
|
47
|
+
exec(`${command} "${url}"`);
|
|
48
|
+
}
|
|
49
|
+
export async function authenticate() {
|
|
50
|
+
const convexUrl = DEFAULT_CONVEX_URL;
|
|
51
|
+
const httpUrl = convexUrl.replace(".convex.cloud", ".convex.site");
|
|
52
|
+
console.log("Authenticating with Sticky Rice...\n");
|
|
53
|
+
// Request device code
|
|
54
|
+
const { deviceCode, userCode, verificationUri } = await requestDeviceCode(httpUrl);
|
|
55
|
+
console.log("Open this URL in your browser:\n");
|
|
56
|
+
console.log(` ${verificationUri}\n`);
|
|
57
|
+
console.log(`Verify this code matches: ${deviceCode}\n`);
|
|
58
|
+
// Try to open browser automatically
|
|
59
|
+
try {
|
|
60
|
+
await openBrowser(verificationUri);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Ignore if browser fails to open
|
|
64
|
+
}
|
|
65
|
+
console.log("Waiting for authorization...");
|
|
66
|
+
// Poll for token
|
|
67
|
+
try {
|
|
68
|
+
const apiKey = await pollForToken(httpUrl, userCode);
|
|
69
|
+
// Save config
|
|
70
|
+
writeConfig({
|
|
71
|
+
apiKey,
|
|
72
|
+
convexUrl,
|
|
73
|
+
});
|
|
74
|
+
console.log("\n✓ Authenticated successfully!");
|
|
75
|
+
console.log(`\nConfig saved to: ${getConfigPath()}`);
|
|
76
|
+
console.log("\nYou can now configure Claude with:\n");
|
|
77
|
+
console.log(JSON.stringify({
|
|
78
|
+
mcpServers: {
|
|
79
|
+
stickyrice: {
|
|
80
|
+
command: "npx",
|
|
81
|
+
args: ["-y", "stickyrice-mcp"],
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
}, null, 2));
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error("\n✗ Authentication failed:", error instanceof Error ? error.message : error);
|
|
88
|
+
process.exit(1);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export async function logout() {
|
|
92
|
+
const config = readConfig();
|
|
93
|
+
if (!config) {
|
|
94
|
+
console.log("Not currently authenticated.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
deleteConfig();
|
|
98
|
+
console.log("Logged out successfully.");
|
|
99
|
+
}
|
|
100
|
+
export async function status() {
|
|
101
|
+
const config = readConfig();
|
|
102
|
+
if (!config) {
|
|
103
|
+
console.log("Not authenticated.");
|
|
104
|
+
console.log("\nRun 'stickyrice-mcp auth' to authenticate.");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
console.log("Authenticated");
|
|
108
|
+
console.log(`Config: ${getConfigPath()}`);
|
|
109
|
+
console.log(`Convex URL: ${config.convexUrl}`);
|
|
110
|
+
console.log(`API Key: ${config.apiKey.substring(0, 10)}...`);
|
|
111
|
+
}
|
|
112
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface Config {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
convexUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function getConfigPath(): string;
|
|
6
|
+
export declare function readConfig(): Config | null;
|
|
7
|
+
export declare function writeConfig(config: Config): void;
|
|
8
|
+
export declare function deleteConfig(): void;
|
|
9
|
+
export declare const DEFAULT_CONVEX_URL = "https://glad-dragon-481.convex.cloud";
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,UAAU,MAAM;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,wBAAgB,UAAU,IAAI,MAAM,GAAG,IAAI,CAU1C;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAKhD;AAED,wBAAgB,YAAY,IAAI,IAAI,CASnC;AAGD,eAAO,MAAM,kBAAkB,yCAAyC,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { homedir } from "os";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
const CONFIG_DIR = join(homedir(), ".config", "stickyrice-mcp");
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, "config.json");
|
|
6
|
+
export function getConfigPath() {
|
|
7
|
+
return CONFIG_FILE;
|
|
8
|
+
}
|
|
9
|
+
export function readConfig() {
|
|
10
|
+
try {
|
|
11
|
+
if (!existsSync(CONFIG_FILE)) {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
const content = readFileSync(CONFIG_FILE, "utf-8");
|
|
15
|
+
return JSON.parse(content);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function writeConfig(config) {
|
|
22
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
23
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
26
|
+
}
|
|
27
|
+
export function deleteConfig() {
|
|
28
|
+
try {
|
|
29
|
+
if (existsSync(CONFIG_FILE)) {
|
|
30
|
+
const { unlinkSync } = require("fs");
|
|
31
|
+
unlinkSync(CONFIG_FILE);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// Ignore errors
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Default Convex URL for Sticky Rice
|
|
39
|
+
export const DEFAULT_CONVEX_URL = "https://glad-dragon-481.convex.cloud";
|
|
40
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAO5B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;AAChE,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEpD,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAW,CAAC;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAc;IACxC,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC5B,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;YACrC,UAAU,CAAC,WAAW,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,gBAAgB;IAClB,CAAC;AACH,CAAC;AAED,qCAAqC;AACrC,MAAM,CAAC,MAAM,kBAAkB,GAAG,sCAAsC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
interface ConvexClientConfig {
|
|
2
|
+
url: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class StickyRiceClient {
|
|
6
|
+
private convexUrl;
|
|
7
|
+
private apiKey;
|
|
8
|
+
private userId;
|
|
9
|
+
private httpUrl;
|
|
10
|
+
constructor(config: ConvexClientConfig);
|
|
11
|
+
authenticate(): Promise<string>;
|
|
12
|
+
getUserId(): string;
|
|
13
|
+
query<T>(fn: string, args?: Record<string, unknown>): Promise<T>;
|
|
14
|
+
mutation<T>(fn: string, args?: Record<string, unknown>): Promise<T>;
|
|
15
|
+
}
|
|
16
|
+
export declare function createClient(convexUrl: string, apiKey: string): StickyRiceClient;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=convex-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convex-client.d.ts","sourceRoot":"","sources":["../src/convex-client.ts"],"names":[],"mappings":"AAAA,UAAU,kBAAkB;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,kBAAkB;IAQhC,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAmBrC,SAAS,IAAI,MAAM;IAQb,KAAK,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAoBpE,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,OAAO,CAAC,CAAC,CAAC;CAkB9E;AAED,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,gBAAgB,CAEhF"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export class StickyRiceClient {
|
|
2
|
+
convexUrl;
|
|
3
|
+
apiKey;
|
|
4
|
+
userId = null;
|
|
5
|
+
httpUrl;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.convexUrl = config.url;
|
|
8
|
+
this.apiKey = config.apiKey;
|
|
9
|
+
// Convert deployment URL to HTTP URL
|
|
10
|
+
// e.g., https://xxx.convex.cloud -> https://xxx.convex.site
|
|
11
|
+
this.httpUrl = config.url.replace(".convex.cloud", ".convex.site");
|
|
12
|
+
}
|
|
13
|
+
async authenticate() {
|
|
14
|
+
const response = await fetch(`${this.httpUrl}/mcp/auth`, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: {
|
|
17
|
+
"Content-Type": "application/json",
|
|
18
|
+
"X-API-Key": this.apiKey,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
const error = (await response.json());
|
|
23
|
+
throw new Error(`Authentication failed: ${error.error}`);
|
|
24
|
+
}
|
|
25
|
+
const data = (await response.json());
|
|
26
|
+
this.userId = data.userId;
|
|
27
|
+
return this.userId;
|
|
28
|
+
}
|
|
29
|
+
getUserId() {
|
|
30
|
+
if (!this.userId) {
|
|
31
|
+
throw new Error("Not authenticated. Call authenticate() first.");
|
|
32
|
+
}
|
|
33
|
+
return this.userId;
|
|
34
|
+
}
|
|
35
|
+
// Call a Convex query function via HTTP Action proxy
|
|
36
|
+
async query(fn, args = {}) {
|
|
37
|
+
const response = await fetch(`${this.httpUrl}/mcp/query`, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: {
|
|
40
|
+
"Content-Type": "application/json",
|
|
41
|
+
"X-API-Key": this.apiKey,
|
|
42
|
+
},
|
|
43
|
+
body: JSON.stringify({ fn, args }),
|
|
44
|
+
});
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
const error = await response.text();
|
|
47
|
+
throw new Error(`Query failed: ${error}`);
|
|
48
|
+
}
|
|
49
|
+
const data = (await response.json());
|
|
50
|
+
return data.value;
|
|
51
|
+
}
|
|
52
|
+
// Call a Convex mutation function via HTTP Action proxy
|
|
53
|
+
async mutation(fn, args = {}) {
|
|
54
|
+
const response = await fetch(`${this.httpUrl}/mcp/mutation`, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: {
|
|
57
|
+
"Content-Type": "application/json",
|
|
58
|
+
"X-API-Key": this.apiKey,
|
|
59
|
+
},
|
|
60
|
+
body: JSON.stringify({ fn, args }),
|
|
61
|
+
});
|
|
62
|
+
if (!response.ok) {
|
|
63
|
+
const error = await response.text();
|
|
64
|
+
throw new Error(`Mutation failed: ${error}`);
|
|
65
|
+
}
|
|
66
|
+
const data = (await response.json());
|
|
67
|
+
return data.value;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function createClient(convexUrl, apiKey) {
|
|
71
|
+
return new StickyRiceClient({ url: convexUrl, apiKey });
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=convex-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convex-client.js","sourceRoot":"","sources":["../src/convex-client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createClient } from "./convex-client.js";
|
|
3
|
+
import { runServer } from "./server.js";
|
|
4
|
+
import { readConfig, DEFAULT_CONVEX_URL } from "./config.js";
|
|
5
|
+
import { authenticate, logout, status } from "./auth.js";
|
|
6
|
+
async function main() {
|
|
7
|
+
const args = process.argv.slice(2);
|
|
8
|
+
const command = args[0];
|
|
9
|
+
// Handle CLI commands
|
|
10
|
+
if (command === "auth" || command === "login") {
|
|
11
|
+
await authenticate();
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
if (command === "logout") {
|
|
15
|
+
await logout();
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (command === "status") {
|
|
19
|
+
await status();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (command === "help" || command === "--help" || command === "-h") {
|
|
23
|
+
console.log(`
|
|
24
|
+
stickyrice-mcp - MCP server for Sticky Rice
|
|
25
|
+
|
|
26
|
+
Commands:
|
|
27
|
+
auth Authenticate with Sticky Rice (opens browser)
|
|
28
|
+
logout Remove saved credentials
|
|
29
|
+
status Show current authentication status
|
|
30
|
+
help Show this help message
|
|
31
|
+
|
|
32
|
+
Running without arguments starts the MCP server.
|
|
33
|
+
|
|
34
|
+
Environment Variables (optional if authenticated via 'auth'):
|
|
35
|
+
CONVEX_URL Convex deployment URL
|
|
36
|
+
STICKYRICE_API_KEY API key for authentication
|
|
37
|
+
`);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// Start MCP server
|
|
41
|
+
// Try environment variables first, then saved config
|
|
42
|
+
let convexUrl = process.env.CONVEX_URL;
|
|
43
|
+
let apiKey = process.env.STICKYRICE_API_KEY;
|
|
44
|
+
if (!apiKey) {
|
|
45
|
+
const config = readConfig();
|
|
46
|
+
if (config) {
|
|
47
|
+
apiKey = config.apiKey;
|
|
48
|
+
convexUrl = config.convexUrl;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (!convexUrl) {
|
|
52
|
+
convexUrl = DEFAULT_CONVEX_URL;
|
|
53
|
+
}
|
|
54
|
+
if (!apiKey) {
|
|
55
|
+
console.error("Not authenticated.");
|
|
56
|
+
console.error("");
|
|
57
|
+
console.error("Run 'npx stickyrice-mcp auth' to authenticate, or set:");
|
|
58
|
+
console.error(" STICKYRICE_API_KEY environment variable");
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
const client = createClient(convexUrl, apiKey);
|
|
62
|
+
try {
|
|
63
|
+
console.error("Authenticating with Sticky Rice...");
|
|
64
|
+
await client.authenticate();
|
|
65
|
+
console.error("Authentication successful");
|
|
66
|
+
}
|
|
67
|
+
catch (error) {
|
|
68
|
+
console.error("Authentication failed:", error);
|
|
69
|
+
console.error("");
|
|
70
|
+
console.error("Try running 'npx stickyrice-mcp auth' to re-authenticate.");
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
await runServer(client);
|
|
74
|
+
}
|
|
75
|
+
main().catch((error) => {
|
|
76
|
+
console.error("Fatal error:", error);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Resource } from "@modelcontextprotocol/sdk/types.js";
|
|
2
|
+
import type { StickyRiceClient } from "../convex-client.js";
|
|
3
|
+
export declare function getResources(client: StickyRiceClient): Promise<Resource[]>;
|
|
4
|
+
export declare function handleResourceRead(client: StickyRiceClient, uri: string): Promise<{
|
|
5
|
+
contents: Array<{
|
|
6
|
+
uri: string;
|
|
7
|
+
mimeType: string;
|
|
8
|
+
text: string;
|
|
9
|
+
}>;
|
|
10
|
+
}>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oCAAoC,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,wBAAsB,YAAY,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CA0ChF;AAED,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,gBAAgB,EACxB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,QAAQ,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;CAAE,CAAC,CA+B/E"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
export async function getResources(client) {
|
|
2
|
+
const resources = [
|
|
3
|
+
{
|
|
4
|
+
uri: "stickyrice://boards",
|
|
5
|
+
name: "All Boards",
|
|
6
|
+
description: "List of all user's boards",
|
|
7
|
+
mimeType: "application/json",
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
uri: "stickyrice://tags",
|
|
11
|
+
name: "All Tags",
|
|
12
|
+
description: "User's tag library",
|
|
13
|
+
mimeType: "application/json",
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
uri: "stickyrice://todos",
|
|
17
|
+
name: "All Todos",
|
|
18
|
+
description: "All incomplete todo and doing items across all notes",
|
|
19
|
+
mimeType: "application/json",
|
|
20
|
+
},
|
|
21
|
+
];
|
|
22
|
+
// Add dynamic board resources
|
|
23
|
+
try {
|
|
24
|
+
const boards = await client.query("mcp:listBoards", {});
|
|
25
|
+
for (const board of boards) {
|
|
26
|
+
resources.push({
|
|
27
|
+
uri: `stickyrice://board/${board.id}`,
|
|
28
|
+
name: board.title,
|
|
29
|
+
description: `Board: ${board.title}`,
|
|
30
|
+
mimeType: "application/json",
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// If we can't fetch boards, just return static resources
|
|
36
|
+
}
|
|
37
|
+
return resources;
|
|
38
|
+
}
|
|
39
|
+
export async function handleResourceRead(client, uri) {
|
|
40
|
+
const url = new URL(uri);
|
|
41
|
+
const path = url.pathname.replace(/^\/\//, "");
|
|
42
|
+
let data;
|
|
43
|
+
if (uri === "stickyrice://boards") {
|
|
44
|
+
data = await client.query("mcp:listBoards", {});
|
|
45
|
+
}
|
|
46
|
+
else if (uri === "stickyrice://tags") {
|
|
47
|
+
data = await client.query("mcp:listTags", {});
|
|
48
|
+
}
|
|
49
|
+
else if (uri === "stickyrice://todos") {
|
|
50
|
+
data = await client.query("mcp:listTodos", {});
|
|
51
|
+
}
|
|
52
|
+
else if (path.startsWith("board/")) {
|
|
53
|
+
const boardId = path.replace("board/", "");
|
|
54
|
+
data = await client.query("mcp:getFullBoard", { boardId });
|
|
55
|
+
}
|
|
56
|
+
else if (path.startsWith("note/")) {
|
|
57
|
+
const noteId = path.replace("note/", "");
|
|
58
|
+
data = await client.query("mcp:getNote", { noteId });
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
throw new Error(`Unknown resource: ${uri}`);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
contents: [
|
|
65
|
+
{
|
|
66
|
+
uri,
|
|
67
|
+
mimeType: "application/json",
|
|
68
|
+
text: JSON.stringify(data, null, 2),
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/resources/index.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAwB;IACzD,MAAM,SAAS,GAAe;QAC5B;YACE,GAAG,EAAE,qBAAqB;YAC1B,IAAI,EAAE,YAAY;YAClB,WAAW,EAAE,2BAA2B;YACxC,QAAQ,EAAE,kBAAkB;SAC7B;QACD;YACE,GAAG,EAAE,mBAAmB;YACxB,IAAI,EAAE,UAAU;YAChB,WAAW,EAAE,oBAAoB;YACjC,QAAQ,EAAE,kBAAkB;SAC7B;QACD;YACE,GAAG,EAAE,oBAAoB;YACzB,IAAI,EAAE,WAAW;YACjB,WAAW,EAAE,sDAAsD;YACnE,QAAQ,EAAE,kBAAkB;SAC7B;KACF,CAAC;IAEF,8BAA8B;IAC9B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,KAAK,CAC/B,gBAAgB,EAChB,EAAE,CACH,CAAC;QAEF,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,SAAS,CAAC,IAAI,CAAC;gBACb,GAAG,EAAE,sBAAsB,KAAK,CAAC,EAAE,EAAE;gBACrC,IAAI,EAAE,KAAK,CAAC,KAAK;gBACjB,WAAW,EAAE,UAAU,KAAK,CAAC,KAAK,EAAE;gBACpC,QAAQ,EAAE,kBAAkB;aAC7B,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,MAAwB,EACxB,GAAW;IAEX,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;IACzB,MAAM,IAAI,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAE/C,IAAI,IAAa,CAAC;IAElB,IAAI,GAAG,KAAK,qBAAqB,EAAE,CAAC;QAClC,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAClD,CAAC;SAAM,IAAI,GAAG,KAAK,mBAAmB,EAAE,CAAC;QACvC,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAChD,CAAC;SAAM,IAAI,GAAG,KAAK,oBAAoB,EAAE,CAAC;QACxC,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC;IACjD,CAAC;SAAM,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;QAC3C,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,kBAAkB,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IAC7D,CAAC;SAAM,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACzC,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;IACvD,CAAC;SAAM,CAAC;QACN,MAAM,IAAI,KAAK,CAAC,qBAAqB,GAAG,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO;QACL,QAAQ,EAAE;YACR;gBACE,GAAG;gBACH,QAAQ,EAAE,kBAAkB;gBAC5B,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;aACpC;SACF;KACF,CAAC;AACJ,CAAC"}
|