anki-mcp-http 0.7.1 → 0.8.1
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 +5 -19
- package/README.md +152 -35
- package/bin/ankimcp.js +0 -0
- package/dist/anki-config.service.d.ts +2 -2
- package/dist/anki-config.service.js +4 -4
- package/dist/app.module.d.ts +1 -1
- package/dist/app.module.js +7 -7
- package/dist/app.module.js.map +1 -1
- package/dist/bootstrap.d.ts +1 -1
- package/dist/bootstrap.js +4 -4
- package/dist/cli.d.ts +2 -1
- package/dist/cli.js +41 -27
- package/dist/cli.js.map +1 -1
- package/dist/http/guards/origin-validation.guard.d.ts +1 -1
- package/dist/http/guards/origin-validation.guard.js +5 -5
- package/dist/main-http.js +16 -2
- package/dist/main-http.js.map +1 -1
- package/dist/main-stdio.js +2 -2
- package/dist/mcp/clients/__mocks__/anki-connect.client.js +1 -1
- package/dist/mcp/clients/anki-connect.client.d.ts +1 -1
- package/dist/mcp/clients/anki-connect.client.js +7 -7
- package/dist/mcp/config/anki-config.interface.js +1 -1
- package/dist/mcp/primitives/essential/index.d.ts +26 -26
- package/dist/mcp/primitives/essential/index.js +1 -4
- package/dist/mcp/primitives/essential/index.js.map +1 -1
- package/dist/mcp/primitives/essential/prompts/review-session.prompt.js +5 -5
- package/dist/mcp/primitives/essential/prompts/review-session.prompt.js.map +1 -1
- package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.js +10 -8
- package/dist/mcp/primitives/essential/prompts/twenty-rules.prompt/index.js.map +1 -1
- package/dist/mcp/primitives/essential/resources/system-info.resource.js +12 -12
- package/dist/mcp/primitives/essential/tools/add-note.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/add-note.tool.js +27 -30
- package/dist/mcp/primitives/essential/tools/add-note.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/create-deck.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/create-deck.tool.js +15 -15
- package/dist/mcp/primitives/essential/tools/create-deck.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/create-model.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/create-model.tool.js +20 -18
- package/dist/mcp/primitives/essential/tools/create-model.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/delete-notes.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/delete-notes.tool.js +22 -22
- package/dist/mcp/primitives/essential/tools/delete-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/find-notes.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/find-notes.tool.js +14 -14
- package/dist/mcp/primitives/essential/tools/find-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/get-due-cards.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js +17 -15
- package/dist/mcp/primitives/essential/tools/get-due-cards.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/list-decks.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/list-decks.tool.js +10 -10
- package/dist/mcp/primitives/essential/tools/list-decks.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/deleteMediaFile.action.js +3 -3
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.js +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/getMediaFilesNames.action.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/retrieveMediaFile.action.js +3 -3
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.d.ts +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.js +7 -7
- package/dist/mcp/primitives/essential/tools/mediaActions/actions/storeMediaFile.action.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/mediaActions/index.d.ts +5 -5
- package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.js +23 -17
- package/dist/mcp/primitives/essential/tools/mediaActions/mediaActions.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-field-names.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/model-field-names.tool.js +20 -17
- package/dist/mcp/primitives/essential/tools/model-field-names.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-names.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/model-names.tool.js +13 -11
- package/dist/mcp/primitives/essential/tools/model-names.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/model-styling.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/model-styling.tool.js +11 -11
- package/dist/mcp/primitives/essential/tools/model-styling.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/notes-info.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/notes-info.tool.js +19 -19
- package/dist/mcp/primitives/essential/tools/notes-info.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/present-card.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/present-card.tool.js +11 -11
- package/dist/mcp/primitives/essential/tools/present-card.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/rate-card.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/rate-card.tool.js +19 -14
- package/dist/mcp/primitives/essential/tools/rate-card.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/sync.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/sync.tool.js +8 -8
- package/dist/mcp/primitives/essential/tools/sync.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/update-model-styling.tool.d.ts +2 -2
- package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js +19 -19
- package/dist/mcp/primitives/essential/tools/update-model-styling.tool.js.map +1 -1
- package/dist/mcp/primitives/essential/tools/update-note-fields.tool.d.ts +3 -3
- package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js +32 -32
- package/dist/mcp/primitives/essential/tools/update-note-fields.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/index.d.ts +17 -17
- package/dist/mcp/primitives/gui/index.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js +22 -22
- package/dist/mcp/primitives/gui/tools/gui-add-cards.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-browse.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-browse.tool.js +15 -14
- package/dist/mcp/primitives/gui/tools/gui-browse.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-current-card.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js +13 -13
- package/dist/mcp/primitives/gui/tools/gui-current-card.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js +12 -12
- package/dist/mcp/primitives/gui/tools/gui-deck-browser.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js +15 -12
- package/dist/mcp/primitives/gui/tools/gui-deck-overview.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js +13 -12
- package/dist/mcp/primitives/gui/tools/gui-edit-note.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-select-card.tool.d.ts +2 -2
- package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js +18 -15
- package/dist/mcp/primitives/gui/tools/gui-select-card.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js +15 -14
- package/dist/mcp/primitives/gui/tools/gui-selected-notes.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js +15 -15
- package/dist/mcp/primitives/gui/tools/gui-show-answer.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-show-question.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js +15 -15
- package/dist/mcp/primitives/gui/tools/gui-show-question.tool.js.map +1 -1
- package/dist/mcp/primitives/gui/tools/gui-undo.tool.d.ts +3 -3
- package/dist/mcp/primitives/gui/tools/gui-undo.tool.js +15 -15
- package/dist/mcp/primitives/gui/tools/gui-undo.tool.js.map +1 -1
- package/dist/mcp/types/anki.types.d.ts +2 -2
- package/dist/mcp/utils/anki.utils.d.ts +3 -3
- package/dist/mcp/utils/anki.utils.js +42 -38
- package/dist/mcp/utils/anki.utils.js.map +1 -1
- package/dist/mcp/utils/markdown.utils.js +16 -12
- package/dist/mcp/utils/markdown.utils.js.map +1 -1
- package/dist/mcp/utils/mcpb-workarounds.js +2 -2
- package/dist/mcp/utils/mcpb-workarounds.js.map +1 -1
- package/dist/services/ngrok.service.d.ts +15 -0
- package/dist/services/ngrok.service.js +120 -0
- package/dist/services/ngrok.service.js.map +1 -0
- package/dist/test-fixtures/mock-data.d.ts +2 -2
- package/dist/test-fixtures/mock-data.js +46 -46
- package/dist/test-fixtures/mock-data.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +12 -7
package/LICENSE
CHANGED
|
@@ -1,21 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
Anki MCP Server is licensed under the GNU Affero General Public License,
|
|
2
|
+
version 3 or later.
|
|
2
3
|
|
|
3
|
-
Copyright (
|
|
4
|
+
Copyright (C) 2025 Anatoly Tarnavsky
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
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.
|
|
6
|
+
For the full text of the AGPL-3.0 license, see:
|
|
7
|
+
https://www.gnu.org/licenses/agpl-3.0.txt
|
package/README.md
CHANGED
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
# Anki MCP
|
|
1
|
+
# Anki MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/ankimcp/anki-mcp-server/actions/workflows/test.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/@ankimcp/anki-mcp-server)
|
|
5
|
+
|
|
6
|
+
<div align="center">
|
|
7
|
+
<img src="./docs/images/ankimcp.png" alt="Anki + MCP Integration" width="600" />
|
|
8
|
+
|
|
9
|
+
<p><strong>Seamlessly integrate <a href="https://apps.ankiweb.net">Anki</a> with AI assistants through the <a href="https://modelcontextprotocol.io">Model Context Protocol</a></strong></p>
|
|
10
|
+
</div>
|
|
2
11
|
|
|
3
12
|
**Beta** - This project is in active development. APIs and features may change.
|
|
4
13
|
|
|
@@ -38,6 +47,13 @@ For comprehensive guides, real-world examples, and step-by-step tutorials on usi
|
|
|
38
47
|
- `getMediaFilesNames` - List media files with optional pattern filtering
|
|
39
48
|
- `deleteMediaFile` - Remove media files
|
|
40
49
|
|
|
50
|
+
**💡 Best Practice for Images:**
|
|
51
|
+
- ✅ **Use file paths** (e.g., `/Users/you/image.png`) - Fast and efficient
|
|
52
|
+
- ✅ **Use URLs** (e.g., `https://example.com/image.jpg`) - Direct download
|
|
53
|
+
- ❌ **Avoid base64** - Extremely slow and token-inefficient
|
|
54
|
+
|
|
55
|
+
Just tell Claude where the image is, and it will handle the upload automatically using the most efficient method.
|
|
56
|
+
|
|
41
57
|
### Model/Template Management
|
|
42
58
|
- `modelNames` - List note types
|
|
43
59
|
- `modelFieldNames` - Get fields for a note type
|
|
@@ -59,7 +75,7 @@ This server works in two modes:
|
|
|
59
75
|
|
|
60
76
|
The easiest way to install this MCP server for Claude Desktop:
|
|
61
77
|
|
|
62
|
-
1. Download the latest `.mcpb` bundle from the [Releases](https://github.com/
|
|
78
|
+
1. Download the latest `.mcpb` bundle from the [Releases](https://github.com/ankimcp/anki-mcp-server/releases) page
|
|
63
79
|
2. In Claude Desktop, install the extension:
|
|
64
80
|
- **Method 1**: Go to Settings → Extensions, then drag and drop the `.mcpb` file
|
|
65
81
|
- **Method 2**: Go to Settings → Developer → Extensions → Install Extension, then select the `.mcpb` file
|
|
@@ -78,16 +94,38 @@ Want to use Anki with MCP clients like **Cursor IDE**, **Cline**, or **Zed Edito
|
|
|
78
94
|
- [Zed Editor](https://zed.dev/) - Fast, modern code editor
|
|
79
95
|
- Other MCP clients that support STDIO transport
|
|
80
96
|
|
|
81
|
-
**
|
|
97
|
+
**Configuration - Choose one method:**
|
|
82
98
|
|
|
83
|
-
|
|
99
|
+
**Method 1: Using npx (recommended - no installation needed)**
|
|
84
100
|
|
|
85
101
|
```json
|
|
86
102
|
{
|
|
87
103
|
"mcpServers": {
|
|
88
104
|
"anki-mcp": {
|
|
89
105
|
"command": "npx",
|
|
90
|
-
"args": ["-y", "anki-mcp-
|
|
106
|
+
"args": ["-y", "@ankimcp/anki-mcp-server", "--stdio"],
|
|
107
|
+
"env": {
|
|
108
|
+
"ANKI_CONNECT_URL": "http://localhost:8765"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Method 2: Using global installation**
|
|
116
|
+
|
|
117
|
+
First, install globally:
|
|
118
|
+
```bash
|
|
119
|
+
npm install -g @ankimcp/anki-mcp-server
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Then configure:
|
|
123
|
+
```json
|
|
124
|
+
{
|
|
125
|
+
"mcpServers": {
|
|
126
|
+
"anki-mcp": {
|
|
127
|
+
"command": "@ankimcp/anki-mcp-server",
|
|
128
|
+
"args": ["--stdio"],
|
|
91
129
|
"env": {
|
|
92
130
|
"ANKI_CONNECT_URL": "http://localhost:8765"
|
|
93
131
|
}
|
|
@@ -109,21 +147,48 @@ Want to use Anki with ChatGPT or Claude.ai in your browser? This mode lets you c
|
|
|
109
147
|
|
|
110
148
|
**How it works (simple explanation):**
|
|
111
149
|
1. You run a small server on your computer (where Anki is installed)
|
|
112
|
-
2.
|
|
113
|
-
3.
|
|
150
|
+
2. Use the built-in `--ngrok` flag to automatically create a public tunnel URL
|
|
151
|
+
3. Share that URL with ChatGPT or Claude.ai
|
|
114
152
|
4. Now the AI can talk to your Anki through the internet!
|
|
115
153
|
|
|
116
|
-
**
|
|
154
|
+
**New in v0.8.0:** Integrated ngrok support with the `--ngrok` flag - no need to run ngrok separately!
|
|
155
|
+
|
|
156
|
+
**Setup - Choose one method:**
|
|
157
|
+
|
|
158
|
+
**Method 1: Using npx (recommended - no installation needed)**
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
# Quick start
|
|
162
|
+
npx @ankimcp/anki-mcp-server
|
|
163
|
+
|
|
164
|
+
# With ngrok tunnel (recommended for web-based AI)
|
|
165
|
+
npx @ankimcp/anki-mcp-server --ngrok
|
|
166
|
+
|
|
167
|
+
# With custom options
|
|
168
|
+
npx @ankimcp/anki-mcp-server --port 8080 --host 0.0.0.0
|
|
169
|
+
npx @ankimcp/anki-mcp-server --anki-connect http://localhost:8765
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Method 2: Using global installation**
|
|
117
173
|
|
|
118
174
|
```bash
|
|
119
|
-
#
|
|
120
|
-
|
|
175
|
+
# Install once
|
|
176
|
+
npm install -g @ankimcp/anki-mcp-server
|
|
177
|
+
|
|
178
|
+
# Run the server
|
|
179
|
+
@ankimcp/anki-mcp-server
|
|
180
|
+
|
|
181
|
+
# With ngrok tunnel (recommended for web-based AI)
|
|
182
|
+
@ankimcp/anki-mcp-server --ngrok
|
|
121
183
|
|
|
122
184
|
# With custom options
|
|
123
|
-
|
|
124
|
-
|
|
185
|
+
@ankimcp/anki-mcp-server --port 8080 --host 0.0.0.0
|
|
186
|
+
@ankimcp/anki-mcp-server --anki-connect http://localhost:8765
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Method 3: Install from source (for development)**
|
|
125
190
|
|
|
126
|
-
|
|
191
|
+
```bash
|
|
127
192
|
npm install
|
|
128
193
|
npm run build
|
|
129
194
|
npm run start:prod:http
|
|
@@ -132,37 +197,66 @@ npm run start:prod:http
|
|
|
132
197
|
**CLI Options:**
|
|
133
198
|
|
|
134
199
|
```bash
|
|
135
|
-
ankimcp [options]
|
|
200
|
+
@ankimcp/anki-mcp-server [options]
|
|
136
201
|
|
|
137
202
|
Options:
|
|
138
203
|
--stdio Run in STDIO mode (for MCP clients)
|
|
139
204
|
-p, --port <port> Port to listen on (HTTP mode, default: 3000)
|
|
140
205
|
-h, --host <host> Host to bind to (HTTP mode, default: 127.0.0.1)
|
|
141
206
|
-a, --anki-connect <url> AnkiConnect URL (default: http://localhost:8765)
|
|
207
|
+
--ngrok Start ngrok tunnel (requires global ngrok installation)
|
|
142
208
|
--help Show help message
|
|
143
209
|
|
|
144
|
-
|
|
145
|
-
ankimcp #
|
|
146
|
-
ankimcp --port 8080 # Custom port
|
|
147
|
-
ankimcp --
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
210
|
+
Usage with npx (no installation needed):
|
|
211
|
+
npx @ankimcp/anki-mcp-server # HTTP mode
|
|
212
|
+
npx @ankimcp/anki-mcp-server --port 8080 # Custom port
|
|
213
|
+
npx @ankimcp/anki-mcp-server --stdio # STDIO mode
|
|
214
|
+
npx @ankimcp/anki-mcp-server --ngrok # HTTP mode with ngrok tunnel
|
|
215
|
+
|
|
216
|
+
Usage with global installation:
|
|
217
|
+
npm install -g @ankimcp/anki-mcp-server # Install once
|
|
218
|
+
@ankimcp/anki-mcp-server # HTTP mode
|
|
219
|
+
@ankimcp/anki-mcp-server --port 8080 # Custom port
|
|
220
|
+
@ankimcp/anki-mcp-server --stdio # STDIO mode
|
|
221
|
+
@ankimcp/anki-mcp-server --ngrok # HTTP mode with ngrok tunnel
|
|
151
222
|
```
|
|
152
223
|
|
|
153
224
|
**Using with ngrok:**
|
|
154
225
|
|
|
226
|
+
**Method 1: Integrated (Recommended - One Command)**
|
|
227
|
+
|
|
155
228
|
```bash
|
|
156
|
-
#
|
|
157
|
-
|
|
229
|
+
# One-time setup (if you haven't already):
|
|
230
|
+
npm install -g ngrok
|
|
231
|
+
ngrok config add-authtoken <your-token> # Get token from https://dashboard.ngrok.com
|
|
232
|
+
|
|
233
|
+
# Start server with ngrok tunnel in one command:
|
|
234
|
+
@ankimcp/anki-mcp-server --ngrok
|
|
235
|
+
|
|
236
|
+
# The tunnel URL will be displayed in the startup banner
|
|
237
|
+
# Example output:
|
|
238
|
+
# 🌐 Ngrok tunnel: https://abc123.ngrok-free.app
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
**Method 2: Manual (Two Terminals)**
|
|
158
242
|
|
|
159
|
-
|
|
243
|
+
```bash
|
|
244
|
+
# Terminal 1: Start the server
|
|
245
|
+
@ankimcp/anki-mcp-server
|
|
246
|
+
|
|
247
|
+
# Terminal 2: Create tunnel
|
|
160
248
|
ngrok http 3000
|
|
161
249
|
|
|
162
|
-
#
|
|
163
|
-
#
|
|
250
|
+
# Copy the ngrok URL (looks like: https://abc123.ngrok-free.app)
|
|
251
|
+
# Share this URL with your AI assistant
|
|
164
252
|
```
|
|
165
253
|
|
|
254
|
+
**Benefits of `--ngrok` flag:**
|
|
255
|
+
- ✅ One command instead of two terminals
|
|
256
|
+
- ✅ Automatic cleanup when you press Ctrl+C
|
|
257
|
+
- ✅ URL displayed directly in the startup banner
|
|
258
|
+
- ✅ Works with custom ports: `@ankimcp/anki-mcp-server --port 8080 --ngrok`
|
|
259
|
+
|
|
166
260
|
**Security note:** Anyone with your ngrok URL can access your Anki, so keep that URL private!
|
|
167
261
|
|
|
168
262
|
### Option 4: Manual Installation from Source (Local Mode)
|
|
@@ -189,7 +283,7 @@ Add the following to your Claude Desktop config:
|
|
|
189
283
|
"mcpServers": {
|
|
190
284
|
"anki-mcp": {
|
|
191
285
|
"command": "node",
|
|
192
|
-
"args": ["/path/to/anki-mcp-
|
|
286
|
+
"args": ["/path/to/anki-mcp-server/dist/main-stdio.js"],
|
|
193
287
|
"env": {
|
|
194
288
|
"ANKI_CONNECT_URL": "http://localhost:8765"
|
|
195
289
|
}
|
|
@@ -198,7 +292,7 @@ Add the following to your Claude Desktop config:
|
|
|
198
292
|
}
|
|
199
293
|
```
|
|
200
294
|
|
|
201
|
-
Replace `/path/to/anki-mcp-
|
|
295
|
+
Replace `/path/to/anki-mcp-server` with your actual project path.
|
|
202
296
|
|
|
203
297
|
### Config File Locations
|
|
204
298
|
|
|
@@ -345,7 +439,7 @@ This command will:
|
|
|
345
439
|
3. Build the TypeScript project
|
|
346
440
|
4. Package `dist/` and `node_modules/` into an `.mcpb` file
|
|
347
441
|
|
|
348
|
-
The output file will be named based on the current version (e.g.,
|
|
442
|
+
The output file will be named based on the current version (e.g., `@ankimcp/anki-mcp-server-0.5.0.mcpb`) and can be distributed for one-click installation.
|
|
349
443
|
|
|
350
444
|
#### What Gets Bundled
|
|
351
445
|
|
|
@@ -458,7 +552,7 @@ Update your Claude Desktop config to enable debugging:
|
|
|
458
552
|
"command": "node",
|
|
459
553
|
"args": [
|
|
460
554
|
"--inspect=9229",
|
|
461
|
-
"
|
|
555
|
+
"<path_to_project>/anki-mcp-server/dist/main-stdio.js"
|
|
462
556
|
],
|
|
463
557
|
"env": {
|
|
464
558
|
"ANKI_CONNECT_URL": "http://localhost:8765"
|
|
@@ -547,10 +641,10 @@ Test the npm package locally before publishing:
|
|
|
547
641
|
|
|
548
642
|
```bash
|
|
549
643
|
# 1. Create local package
|
|
550
|
-
npm run pack:local # Builds and creates anki-mcp-
|
|
644
|
+
npm run pack:local # Builds and creates @ankimcp/anki-mcp-server-*.tgz
|
|
551
645
|
|
|
552
646
|
# 2. Install globally from local package
|
|
553
|
-
npm run install:local # Installs from
|
|
647
|
+
npm run install:local # Installs from ./@ankimcp/anki-mcp-server-*.tgz
|
|
554
648
|
|
|
555
649
|
# 3. Test the command
|
|
556
650
|
ankimcp # Runs HTTP server on port 3000
|
|
@@ -601,7 +695,7 @@ This project follows [Semantic Versioning](https://semver.org/) with a pre-1.0 d
|
|
|
601
695
|
- Will be released when the API is stable and tested
|
|
602
696
|
- Breaking changes will require major version bumps (2.0.0, etc.)
|
|
603
697
|
|
|
604
|
-
**Current Status**: `0.
|
|
698
|
+
**Current Status**: `0.8.0` - Active beta development. New features include integrated ngrok tunneling (`--ngrok` flag), the `twenty_rules` prompt for evidence-based flashcard creation, media file management, and improved prompt system. APIs may change based on feedback and testing.
|
|
605
699
|
|
|
606
700
|
## Similar Projects
|
|
607
701
|
|
|
@@ -616,7 +710,7 @@ If you're exploring Anki MCP integrations, here are other projects in this space
|
|
|
616
710
|
- **Architecture**: Procedural code structure with all tools in one file
|
|
617
711
|
- **Good for**: Simple use cases, minimal dependencies
|
|
618
712
|
|
|
619
|
-
**Why this project
|
|
713
|
+
**Why this project differs:**
|
|
620
714
|
- **Enterprise-grade architecture**: Built on NestJS with dependency injection
|
|
621
715
|
- **Modular design**: Each tool is a separate class with clear separation of concerns
|
|
622
716
|
- **Maintainability**: Easy to extend with new features without touching existing code
|
|
@@ -636,4 +730,27 @@ If you're exploring Anki MCP integrations, here are other projects in this space
|
|
|
636
730
|
- [Building Desktop Extensions (Anthropic Blog)](https://www.anthropic.com/engineering/desktop-extensions)
|
|
637
731
|
- [MCP Servers Repository](https://github.com/modelcontextprotocol/servers)
|
|
638
732
|
- [NestJS Documentation](https://docs.nestjs.com)
|
|
639
|
-
- [Anki Official Website](https://apps.ankiweb.net/)
|
|
733
|
+
- [Anki Official Website](https://apps.ankiweb.net/)
|
|
734
|
+
|
|
735
|
+
## License & Attribution
|
|
736
|
+
|
|
737
|
+
This project is licensed under the GNU Affero General Public License v3.0 or later (AGPL-3.0-or-later).
|
|
738
|
+
|
|
739
|
+
### Why AGPL-3.0?
|
|
740
|
+
|
|
741
|
+
This license was chosen to maintain compatibility with Anki's AGPL-3.0 license for potential future integration scenarios.
|
|
742
|
+
|
|
743
|
+
**What this means:**
|
|
744
|
+
- **Personal use**: Use the software freely
|
|
745
|
+
- **Running as a service for others**: You must provide source code access (AGPL Section 13)
|
|
746
|
+
- **Modifying and distributing**: Share your improvements under AGPL-3.0-or-later
|
|
747
|
+
|
|
748
|
+
For complete license terms, see the [LICENSE](LICENSE) file.
|
|
749
|
+
|
|
750
|
+
### Third-Party Attributions
|
|
751
|
+
|
|
752
|
+
- **Anki®** is a registered trademark of Ankitects Pty Ltd. This project is an unofficial third-party tool and is not affiliated with, endorsed by, or sponsored by Ankitects Pty Ltd. The Anki logo is used under the alternative license for referencing Anki with a link to [https://apps.ankiweb.net](https://apps.ankiweb.net). For the official Anki application, visit [https://apps.ankiweb.net](https://apps.ankiweb.net).
|
|
753
|
+
|
|
754
|
+
- **Model Context Protocol (MCP)** is an open standard by Anthropic. The MCP logo is from the official [MCP documentation repository](https://github.com/modelcontextprotocol/docs) and is used under the MIT License. For more information about MCP, visit [https://modelcontextprotocol.io](https://modelcontextprotocol.io).
|
|
755
|
+
|
|
756
|
+
- This is an independent project that bridges Anki and MCP technologies. All trademarks, service marks, trade names, product names, and logos are the property of their respective owners.
|
package/bin/ankimcp.js
CHANGED
|
File without changes
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ConfigService } from
|
|
2
|
-
import { IAnkiConfig } from
|
|
1
|
+
import { ConfigService } from "@nestjs/config";
|
|
2
|
+
import { IAnkiConfig } from "./mcp/config/anki-config.interface";
|
|
3
3
|
export declare class AnkiConfigService implements IAnkiConfig {
|
|
4
4
|
private configService;
|
|
5
5
|
constructor(configService: ConfigService);
|
|
@@ -19,18 +19,18 @@ let AnkiConfigService = class AnkiConfigService {
|
|
|
19
19
|
this.configService = configService;
|
|
20
20
|
}
|
|
21
21
|
get ankiConnectUrl() {
|
|
22
|
-
return this.configService.get(
|
|
22
|
+
return this.configService.get("ANKI_CONNECT_URL", "http://localhost:8765");
|
|
23
23
|
}
|
|
24
24
|
get ankiConnectApiVersion() {
|
|
25
|
-
const version = this.configService.get(
|
|
25
|
+
const version = this.configService.get("ANKI_CONNECT_API_VERSION", "6");
|
|
26
26
|
return parseInt(version, 10);
|
|
27
27
|
}
|
|
28
28
|
get ankiConnectApiKey() {
|
|
29
|
-
const apiKey = this.configService.get(
|
|
29
|
+
const apiKey = this.configService.get("ANKI_CONNECT_API_KEY");
|
|
30
30
|
return (0, mcpb_workarounds_1.sanitizeMcpbConfigValue)(apiKey);
|
|
31
31
|
}
|
|
32
32
|
get ankiConnectTimeout() {
|
|
33
|
-
const timeout = this.configService.get(
|
|
33
|
+
const timeout = this.configService.get("ANKI_CONNECT_TIMEOUT", "5000");
|
|
34
34
|
return parseInt(timeout, 10);
|
|
35
35
|
}
|
|
36
36
|
};
|
package/dist/app.module.d.ts
CHANGED
package/dist/app.module.js
CHANGED
|
@@ -22,11 +22,11 @@ let AppModule = AppModule_1 = class AppModule {
|
|
|
22
22
|
config_1.ConfigModule.forRoot({
|
|
23
23
|
isGlobal: true,
|
|
24
24
|
cache: true,
|
|
25
|
-
envFilePath: [
|
|
25
|
+
envFilePath: [".env.local", ".env"],
|
|
26
26
|
}),
|
|
27
27
|
mcp_nest_1.McpModule.forRoot({
|
|
28
|
-
name: process.env.MCP_SERVER_NAME ||
|
|
29
|
-
version: process.env.MCP_SERVER_VERSION ||
|
|
28
|
+
name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
|
|
29
|
+
version: process.env.MCP_SERVER_VERSION || "1.0.0",
|
|
30
30
|
transport: mcp_nest_1.McpTransportType.STDIO,
|
|
31
31
|
}),
|
|
32
32
|
essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
|
|
@@ -52,13 +52,13 @@ let AppModule = AppModule_1 = class AppModule {
|
|
|
52
52
|
config_1.ConfigModule.forRoot({
|
|
53
53
|
isGlobal: true,
|
|
54
54
|
cache: true,
|
|
55
|
-
envFilePath: [
|
|
55
|
+
envFilePath: [".env.local", ".env"],
|
|
56
56
|
}),
|
|
57
57
|
mcp_nest_1.McpModule.forRoot({
|
|
58
|
-
name: process.env.MCP_SERVER_NAME ||
|
|
59
|
-
version: process.env.MCP_SERVER_VERSION ||
|
|
58
|
+
name: process.env.MCP_SERVER_NAME || "anki-mcp-server",
|
|
59
|
+
version: process.env.MCP_SERVER_VERSION || "1.0.0",
|
|
60
60
|
transport: mcp_nest_1.McpTransportType.STREAMABLE_HTTP,
|
|
61
|
-
mcpEndpoint:
|
|
61
|
+
mcpEndpoint: "/",
|
|
62
62
|
}),
|
|
63
63
|
essential_1.McpPrimitivesAnkiEssentialModule.forRoot({
|
|
64
64
|
ankiConfigProvider: {
|
package/dist/app.module.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2CAA8C;AAC9C,8CAA8D;AAC9D,0DAGoC;AACpC,8CAAkE;AAClE,+DAA0D;AAGnD,IAAM,SAAS,iBAAf,MAAM,SAAS;IAIpB,MAAM,CAAC,QAAQ;QACb,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,
|
|
1
|
+
{"version":3,"file":"app.module.js","sourceRoot":"","sources":["../src/app.module.ts"],"names":[],"mappings":";;;;;;;;;;AAAA,2CAAuD;AACvD,2CAA8C;AAC9C,8CAA8D;AAC9D,0DAGoC;AACpC,8CAAkE;AAClE,+DAA0D;AAGnD,IAAM,SAAS,iBAAf,MAAM,SAAS;IAIpB,MAAM,CAAC,QAAQ;QACb,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,KAAK;iBAClC,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YACD,SAAS,EAAE,CAAC,uCAAiB,CAAC;SAC/B,CAAC;IACJ,CAAC;IAKD,MAAM,CAAC,OAAO;QACZ,OAAO;YACL,MAAM,EAAE,WAAS;YACjB,OAAO,EAAE;gBAEP,qBAAY,CAAC,OAAO,CAAC;oBACnB,QAAQ,EAAE,IAAI;oBACd,KAAK,EAAE,IAAI;oBACX,WAAW,EAAE,CAAC,YAAY,EAAE,MAAM,CAAC;iBACpC,CAAC;gBAGF,oBAAS,CAAC,OAAO,CAAC;oBAChB,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,iBAAiB;oBACtD,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,OAAO;oBAClD,SAAS,EAAE,2BAAgB,CAAC,eAAe;oBAC3C,WAAW,EAAE,GAAG;iBACjB,CAAC;gBAGF,4CAAgC,CAAC,OAAO,CAAC;oBACvC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;gBAGF,gCAA0B,CAAC,OAAO,CAAC;oBACjC,kBAAkB,EAAE;wBAClB,OAAO,EAAE,uBAAW;wBACpB,QAAQ,EAAE,uCAAiB;qBAC5B;iBACF,CAAC;aACH;YACD,SAAS,EAAE,CAAC,uCAAiB,CAAC;SAC/B,CAAC;IACJ,CAAC;CACF,CAAA;AAnFY,8BAAS;oBAAT,SAAS;IADrB,IAAA,eAAM,EAAC,EAAE,CAAC;GACE,SAAS,CAmFrB"}
|
package/dist/bootstrap.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { LoggerService } from
|
|
1
|
+
import { LoggerService } from "@nestjs/common";
|
|
2
2
|
export declare function createPinoLogger(destination: 1 | 2): import("pino").Logger<never, boolean>;
|
|
3
3
|
export declare function createLoggerService(pinoLogger: any): LoggerService;
|
package/dist/bootstrap.js
CHANGED
|
@@ -5,14 +5,14 @@ exports.createLoggerService = createLoggerService;
|
|
|
5
5
|
const pino_1 = require("pino");
|
|
6
6
|
function createPinoLogger(destination) {
|
|
7
7
|
return (0, pino_1.pino)({
|
|
8
|
-
level: process.env.LOG_LEVEL ||
|
|
8
|
+
level: process.env.LOG_LEVEL || "info",
|
|
9
9
|
transport: {
|
|
10
|
-
target:
|
|
10
|
+
target: "pino-pretty",
|
|
11
11
|
options: {
|
|
12
12
|
destination,
|
|
13
13
|
colorize: true,
|
|
14
|
-
translateTime:
|
|
15
|
-
ignore:
|
|
14
|
+
translateTime: "HH:MM:ss Z",
|
|
15
|
+
ignore: "pid,hostname",
|
|
16
16
|
},
|
|
17
17
|
},
|
|
18
18
|
});
|
package/dist/cli.d.ts
CHANGED
|
@@ -2,7 +2,8 @@ export interface CliOptions {
|
|
|
2
2
|
port: number;
|
|
3
3
|
host: string;
|
|
4
4
|
ankiConnect: string;
|
|
5
|
+
ngrok: boolean;
|
|
5
6
|
}
|
|
6
7
|
export declare function checkForUpdates(): void;
|
|
7
8
|
export declare function parseCliArgs(): CliOptions;
|
|
8
|
-
export declare function displayStartupBanner(options: CliOptions): void;
|
|
9
|
+
export declare function displayStartupBanner(options: CliOptions, ngrokUrl?: string): void;
|
package/dist/cli.js
CHANGED
|
@@ -12,10 +12,10 @@ const path_1 = require("path");
|
|
|
12
12
|
const update_notifier_1 = __importDefault(require("update-notifier"));
|
|
13
13
|
function getPackageJson() {
|
|
14
14
|
try {
|
|
15
|
-
return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname,
|
|
15
|
+
return JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "../package.json"), "utf-8"));
|
|
16
16
|
}
|
|
17
17
|
catch {
|
|
18
|
-
return { version:
|
|
18
|
+
return { version: "0.0.0", name: "anki-mcp-http" };
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
21
|
function getVersion() {
|
|
@@ -27,26 +27,32 @@ function checkForUpdates() {
|
|
|
27
27
|
function parseCliArgs() {
|
|
28
28
|
const program = new commander_1.Command();
|
|
29
29
|
program
|
|
30
|
-
.name(
|
|
31
|
-
.description(
|
|
30
|
+
.name("ankimcp")
|
|
31
|
+
.description("AnkiMCP Server - Model Context Protocol server for Anki")
|
|
32
32
|
.version(getVersion())
|
|
33
|
-
.option(
|
|
34
|
-
.option(
|
|
35
|
-
.option(
|
|
36
|
-
.option(
|
|
37
|
-
.
|
|
33
|
+
.option("--stdio", "Run in STDIO mode (for MCP clients like Cursor, Cline, Zed)")
|
|
34
|
+
.option("-p, --port <number>", "Port to listen on (HTTP mode)", "3000")
|
|
35
|
+
.option("-h, --host <address>", "Host to bind to (HTTP mode)", "127.0.0.1")
|
|
36
|
+
.option("-a, --anki-connect <url>", "AnkiConnect URL", "http://localhost:8765")
|
|
37
|
+
.option("--ngrok", "Start ngrok tunnel (requires global ngrok installation)")
|
|
38
|
+
.addHelpText("after", `
|
|
38
39
|
Transport Modes:
|
|
39
40
|
HTTP Mode (default): For web-based AI assistants (ChatGPT, Claude.ai)
|
|
40
41
|
STDIO Mode: For desktop MCP clients (Cursor, Cline, Zed)
|
|
41
42
|
|
|
42
43
|
Examples - HTTP Mode:
|
|
43
|
-
$
|
|
44
|
-
$
|
|
45
|
-
$
|
|
46
|
-
$
|
|
44
|
+
$ anki-mcp-http # Use defaults
|
|
45
|
+
$ anki-mcp-http --port 8080 # Custom port
|
|
46
|
+
$ anki-mcp-http --host 0.0.0.0 --port 3000 # Listen on all interfaces
|
|
47
|
+
$ anki-mcp-http --anki-connect http://localhost:8765
|
|
48
|
+
|
|
49
|
+
Examples - HTTP Mode with Ngrok:
|
|
50
|
+
$ anki-mcp-http --ngrok # Start with ngrok tunnel
|
|
51
|
+
$ anki-mcp-http --port 8080 --ngrok # Custom port + ngrok
|
|
52
|
+
$ anki-mcp-http --host 0.0.0.0 --ngrok # Public host + ngrok
|
|
47
53
|
|
|
48
54
|
Examples - STDIO Mode:
|
|
49
|
-
$
|
|
55
|
+
$ anki-mcp-http --stdio # For use with npx in MCP clients
|
|
50
56
|
|
|
51
57
|
# MCP client configuration (Cursor, Cline, Zed, etc.):
|
|
52
58
|
{
|
|
@@ -58,10 +64,11 @@ Examples - STDIO Mode:
|
|
|
58
64
|
}
|
|
59
65
|
}
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
1.
|
|
63
|
-
2.
|
|
64
|
-
3.
|
|
67
|
+
Ngrok Setup (one-time):
|
|
68
|
+
1. Install: npm install -g ngrok
|
|
69
|
+
2. Get auth token from: https://dashboard.ngrok.com/get-started/your-authtoken
|
|
70
|
+
3. Setup: ngrok config add-authtoken <your-token>
|
|
71
|
+
4. Run: anki-mcp-http --ngrok
|
|
65
72
|
`);
|
|
66
73
|
program.parse();
|
|
67
74
|
const options = program.opts();
|
|
@@ -69,32 +76,39 @@ Usage with ngrok (HTTP mode only):
|
|
|
69
76
|
port: parseInt(options.port.toString(), 10),
|
|
70
77
|
host: options.host,
|
|
71
78
|
ankiConnect: options.ankiConnect,
|
|
79
|
+
ngrok: options.ngrok || false,
|
|
72
80
|
};
|
|
73
81
|
}
|
|
74
|
-
function displayStartupBanner(options) {
|
|
82
|
+
function displayStartupBanner(options, ngrokUrl) {
|
|
75
83
|
const version = getVersion();
|
|
76
84
|
const title = `AnkiMCP HTTP Server v${version}`;
|
|
77
85
|
const padding = Math.floor((64 - title.length) / 2);
|
|
78
|
-
const paddedTitle =
|
|
86
|
+
const paddedTitle = " ".repeat(padding) + title + " ".repeat(64 - padding - title.length);
|
|
79
87
|
console.log(`
|
|
80
88
|
╔════════════════════════════════════════════════════════════════╗
|
|
81
89
|
║${paddedTitle}║
|
|
82
90
|
╚════════════════════════════════════════════════════════════════╝
|
|
83
91
|
|
|
84
92
|
🚀 Server running on: http://${options.host}:${options.port}
|
|
85
|
-
🔌 AnkiConnect URL: ${options.ankiConnect}
|
|
93
|
+
🔌 AnkiConnect URL: ${options.ankiConnect}${ngrokUrl ? `\n🌐 Ngrok tunnel: ${ngrokUrl}` : ""}
|
|
86
94
|
|
|
87
95
|
Configuration:
|
|
88
96
|
• Port: ${options.port} (override: --port 8080)
|
|
89
97
|
• Host: ${options.host} (override: --host 0.0.0.0)
|
|
90
98
|
• AnkiConnect: ${options.ankiConnect}
|
|
91
|
-
(override: --anki-connect http://localhost:8765)
|
|
92
|
-
|
|
99
|
+
(override: --anki-connect http://localhost:8765)${ngrokUrl ? `\n • Ngrok tunnel: ${ngrokUrl}\n • Ngrok dashboard: http://localhost:4040` : ""}
|
|
100
|
+
${!ngrokUrl
|
|
101
|
+
? `
|
|
93
102
|
Usage with ngrok:
|
|
94
|
-
1.
|
|
95
|
-
2.
|
|
96
|
-
|
|
97
|
-
|
|
103
|
+
1. Install: npm install -g ngrok
|
|
104
|
+
2. Setup: ngrok config add-authtoken <your-token>
|
|
105
|
+
3. Run: anki-mcp-http --ngrok
|
|
106
|
+
`
|
|
107
|
+
: `
|
|
108
|
+
Share this URL with your AI assistant:
|
|
109
|
+
${ngrokUrl}
|
|
110
|
+
`}
|
|
111
|
+
Run 'anki-mcp-http --help' for more options.
|
|
98
112
|
`);
|
|
99
113
|
}
|
|
100
114
|
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";;;;;AA0BA,0CAEC;AAED,oCAuEC;AAED,oDAsCC;AA7ID,yCAAoC;AACpC,2BAAkC;AAClC,+BAA4B;AAC5B,sEAA6C;AAS7C,SAAS,cAAc;IACrB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CACf,IAAA,iBAAY,EAAC,IAAA,WAAI,EAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAC1D,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;IACrD,CAAC;AACH,CAAC;AAED,SAAS,UAAU;IACjB,OAAO,cAAc,EAAE,CAAC,OAAO,CAAC;AAClC,CAAC;AAED,SAAgB,eAAe;IAC7B,IAAA,yBAAc,EAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;AACrD,CAAC;AAED,SAAgB,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,SAAS,CAAC;SACf,WAAW,CAAC,yDAAyD,CAAC;SACtE,OAAO,CAAC,UAAU,EAAE,CAAC;SACrB,MAAM,CACL,SAAS,EACT,6DAA6D,CAC9D;SACA,MAAM,CAAC,qBAAqB,EAAE,+BAA+B,EAAE,MAAM,CAAC;SACtE,MAAM,CAAC,sBAAsB,EAAE,6BAA6B,EAAE,WAAW,CAAC;SAC1E,MAAM,CACL,0BAA0B,EAC1B,iBAAiB,EACjB,uBAAuB,CACxB;SACA,MAAM,CACL,SAAS,EACT,yDAAyD,CAC1D;SACA,WAAW,CACV,OAAO,EACP;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkCL,CACI,CAAC;IAEJ,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAc,CAAC;IAE3C,OAAO;QACL,IAAI,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE,CAAC;QAC3C,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,KAAK;KAC9B,CAAC;AACJ,CAAC;AAED,SAAgB,oBAAoB,CAClC,OAAmB,EACnB,QAAiB;IAEjB,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,wBAAwB,OAAO,EAAE,CAAC;IAChD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACpD,MAAM,WAAW,GACf,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IAExE,OAAO,CAAC,GAAG,CAAC;;GAEX,WAAW;;;+BAGiB,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI;wBACnC,OAAO,CAAC,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE;;;0BAGzE,OAAO,CAAC,IAAI;0BACZ,OAAO,CAAC,IAAI;0BACZ,OAAO,CAAC,WAAW;0EAC6B,QAAQ,CAAC,CAAC,CAAC,6BAA6B,QAAQ,iDAAiD,CAAC,CAAC,CAAC,EAAE;EAE9K,CAAC,QAAQ;QACP,CAAC,CAAC;;;;;CAKL;QACG,CAAC,CAAC;;IAEF,QAAQ;CAEZ;;CAEC,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -14,9 +14,9 @@ const common_1 = require("@nestjs/common");
|
|
|
14
14
|
let OriginValidationGuard = class OriginValidationGuard {
|
|
15
15
|
allowedOrigins;
|
|
16
16
|
constructor() {
|
|
17
|
-
const defaultOrigins =
|
|
17
|
+
const defaultOrigins = "http://localhost:*,http://127.0.0.1:*,https://localhost:*,https://127.0.0.1:*";
|
|
18
18
|
const originsEnv = process.env.ALLOWED_ORIGINS || defaultOrigins;
|
|
19
|
-
this.allowedOrigins = originsEnv.split(
|
|
19
|
+
this.allowedOrigins = originsEnv.split(",").map((o) => o.trim());
|
|
20
20
|
}
|
|
21
21
|
canActivate(context) {
|
|
22
22
|
const request = context.switchToHttp().getRequest();
|
|
@@ -34,10 +34,10 @@ let OriginValidationGuard = class OriginValidationGuard {
|
|
|
34
34
|
if (origin === pattern) {
|
|
35
35
|
return true;
|
|
36
36
|
}
|
|
37
|
-
if (pattern.includes(
|
|
37
|
+
if (pattern.includes("*")) {
|
|
38
38
|
const regexPattern = pattern
|
|
39
|
-
.replace(/\./g,
|
|
40
|
-
.replace(/\*/g,
|
|
39
|
+
.replace(/\./g, "\\.")
|
|
40
|
+
.replace(/\*/g, ".*");
|
|
41
41
|
const regex = new RegExp(`^${regexPattern}$`);
|
|
42
42
|
return regex.test(origin);
|
|
43
43
|
}
|