@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.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/index.mjs +35 -14
  3. 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
- const items = [];
47
- for (const ws of workspaces) {
48
- try {
49
- const lib = await api(`/api/library?workspace=${encodeURIComponent(ws.id)}`);
50
- for (const it of lib.items || []) items.push(it);
51
- } catch {
52
- // a workspace we can't read (or that errored) skip it, keep the rest.
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.1.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 promptIndex(items)) {
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 { items } = await snapshot();
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.1.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": {