@aistoragedepot/mcp 0.1.0 → 0.2.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/README.md +4 -0
- package/index.mjs +35 -14
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,6 +16,9 @@ Your stored content shows up where you actually work:
|
|
|
16
16
|
|
|
17
17
|
## Setup
|
|
18
18
|
|
|
19
|
+
> **👉 Easiest path:** step-by-step instructions for each app (config-file locations and all)
|
|
20
|
+
> are at **<https://www.aistoragedepot.com/connect>**. The manual version:
|
|
21
|
+
|
|
19
22
|
1. In AIStorageDepot (a **PLUS** plan is required for API tokens), go to **Settings → API
|
|
20
23
|
tokens** and create a token. Copy it.
|
|
21
24
|
2. Add the server to your MCP client's config. Example (Claude Desktop /
|
|
@@ -44,6 +47,7 @@ Your stored content shows up where you actually work:
|
|
|
44
47
|
| --- | --- | --- | --- |
|
|
45
48
|
| `AISD_TOKEN` | yes | — | Token from Settings → API tokens. Has full access to your account — keep it secret. |
|
|
46
49
|
| `AISD_BASE_URL` | no | `https://www.aistoragedepot.com` | Point at a self-hosted / dev instance if needed. |
|
|
50
|
+
| `AISD_WORKSPACES` | no | your personal library | Which workspaces expose **prompts** (slash-commands). Comma-separated workspace names (e.g. `My Library,Engineering`), or `all`. Keeps the slash menu short; **search and resources still cover every workspace** regardless. |
|
|
47
51
|
|
|
48
52
|
## Notes
|
|
49
53
|
|
package/index.mjs
CHANGED
|
@@ -43,15 +43,13 @@ let cache = { at: 0, workspaces: [], items: [] };
|
|
|
43
43
|
async function snapshot() {
|
|
44
44
|
if (cache.items.length && Date.now() - cache.at < 30_000) return cache;
|
|
45
45
|
const workspaces = await api("/api/workspaces");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
54
|
-
}
|
|
46
|
+
// Fetch every workspace's library in parallel — the sequential loop was the slow part.
|
|
47
|
+
const libs = await Promise.all(
|
|
48
|
+
workspaces.map((ws) =>
|
|
49
|
+
api(`/api/library?workspace=${encodeURIComponent(ws.id)}`).catch(() => ({ items: [] })),
|
|
50
|
+
),
|
|
51
|
+
);
|
|
52
|
+
const items = libs.flatMap((lib) => lib.items || []);
|
|
55
53
|
cache = { at: Date.now(), workspaces, items };
|
|
56
54
|
return cache;
|
|
57
55
|
}
|
|
@@ -76,6 +74,31 @@ function promptIndex(items) {
|
|
|
76
74
|
return byName;
|
|
77
75
|
}
|
|
78
76
|
|
|
77
|
+
// Which workspaces' prompts appear as slash-commands. Default: your personal library only —
|
|
78
|
+
// keeps the slash menu short + fast (clients bury/limit long prompt lists). Override with
|
|
79
|
+
// AISD_WORKSPACES="Name1,Name2" (comma-separated workspace names) or AISD_WORKSPACES="all".
|
|
80
|
+
const PROMPT_WS = (process.env.AISD_WORKSPACES || "")
|
|
81
|
+
.split(",")
|
|
82
|
+
.map((s) => s.trim().toLowerCase())
|
|
83
|
+
.filter(Boolean);
|
|
84
|
+
|
|
85
|
+
function promptScopeIds(workspaces) {
|
|
86
|
+
const all = () => new Set(workspaces.map((w) => w.id));
|
|
87
|
+
if (PROMPT_WS.includes("all") || PROMPT_WS.includes("*")) return all();
|
|
88
|
+
if (PROMPT_WS.length) {
|
|
89
|
+
const named = workspaces.filter((w) => PROMPT_WS.includes((w.name || "").toLowerCase()));
|
|
90
|
+
if (named.length) return new Set(named.map((w) => w.id));
|
|
91
|
+
}
|
|
92
|
+
const personal = workspaces.filter((w) => w.type === "PERSONAL");
|
|
93
|
+
return personal.length ? new Set(personal.map((w) => w.id)) : all();
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// promptIndex, but only over items in the in-scope workspaces.
|
|
97
|
+
function scopedPromptIndex(cache) {
|
|
98
|
+
const ids = promptScopeIds(cache.workspaces);
|
|
99
|
+
return promptIndex(cache.items.filter((it) => ids.has(it.workspaceId)));
|
|
100
|
+
}
|
|
101
|
+
|
|
79
102
|
// MCP argument names should be simple identifiers; map them back to the original
|
|
80
103
|
// "[placeholder]" text so we can substitute into the body.
|
|
81
104
|
function argMap(placeholders) {
|
|
@@ -100,7 +123,7 @@ function fillBody(body, placeholders, args) {
|
|
|
100
123
|
}
|
|
101
124
|
|
|
102
125
|
const server = new Server(
|
|
103
|
-
{ name: "aistoragedepot", version: "0.
|
|
126
|
+
{ name: "aistoragedepot", version: "0.2.0" },
|
|
104
127
|
{ capabilities: { resources: {}, prompts: {}, tools: {} } },
|
|
105
128
|
);
|
|
106
129
|
|
|
@@ -128,9 +151,8 @@ server.setRequestHandler(ReadResourceRequestSchema, async (req) => {
|
|
|
128
151
|
|
|
129
152
|
// ---- Prompts: prompt-format items, [fields] → arguments ----
|
|
130
153
|
server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
131
|
-
const { items } = await snapshot();
|
|
132
154
|
const prompts = [];
|
|
133
|
-
for (const [name, it] of
|
|
155
|
+
for (const [name, it] of scopedPromptIndex(await snapshot())) {
|
|
134
156
|
const am = argMap(it.placeholders);
|
|
135
157
|
prompts.push({
|
|
136
158
|
name,
|
|
@@ -146,8 +168,7 @@ server.setRequestHandler(ListPromptsRequestSchema, async () => {
|
|
|
146
168
|
});
|
|
147
169
|
|
|
148
170
|
server.setRequestHandler(GetPromptRequestSchema, async (req) => {
|
|
149
|
-
const
|
|
150
|
-
const it = promptIndex(items).get(req.params.name);
|
|
171
|
+
const it = scopedPromptIndex(await snapshot()).get(req.params.name);
|
|
151
172
|
if (!it) throw new Error(`Unknown prompt: ${req.params.name}`);
|
|
152
173
|
const text = fillBody(it.body, it.placeholders, req.params.arguments || {});
|
|
153
174
|
return {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aistoragedepot/mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Model Context Protocol server for your AIStorageDepot library — exposes your prompts, rules, docs, and skills to MCP-aware AI clients (Claude, Cursor, Cline, …).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|