@nestr/mcp 0.1.72 → 0.1.89
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/build/api/client.d.ts +84 -5
- package/build/api/client.d.ts.map +1 -1
- package/build/api/client.js +120 -21
- package/build/api/client.js.map +1 -1
- package/build/help/articles.d.ts +146 -0
- package/build/help/articles.d.ts.map +1 -0
- package/build/help/articles.js +574 -0
- package/build/help/articles.js.map +1 -0
- package/build/help/cross-links.d.ts +21 -0
- package/build/help/cross-links.d.ts.map +1 -0
- package/build/help/cross-links.js +61 -0
- package/build/help/cross-links.js.map +1 -0
- package/build/help/topics.d.ts.map +1 -1
- package/build/help/topics.js +324 -12
- package/build/help/topics.js.map +1 -1
- package/build/http.d.ts +26 -13
- package/build/http.d.ts.map +1 -1
- package/build/http.js +572 -128
- package/build/http.js.map +1 -1
- package/build/oauth/client-info.d.ts +58 -0
- package/build/oauth/client-info.d.ts.map +1 -0
- package/build/oauth/client-info.js +68 -0
- package/build/oauth/client-info.js.map +1 -0
- package/build/oauth/config.d.ts +19 -0
- package/build/oauth/config.d.ts.map +1 -1
- package/build/oauth/config.js +12 -0
- package/build/oauth/config.js.map +1 -1
- package/build/oauth/flow.d.ts +6 -0
- package/build/oauth/flow.d.ts.map +1 -1
- package/build/oauth/flow.js +30 -4
- package/build/oauth/flow.js.map +1 -1
- package/build/oauth/store.d.ts +14 -0
- package/build/oauth/store.d.ts.map +1 -1
- package/build/oauth/store.js.map +1 -1
- package/build/server.d.ts +11 -0
- package/build/server.d.ts.map +1 -1
- package/build/server.js +38 -5
- package/build/server.js.map +1 -1
- package/build/skills/tension-processing.d.ts.map +1 -1
- package/build/skills/tension-processing.js +11 -1
- package/build/skills/tension-processing.js.map +1 -1
- package/build/tools/index.d.ts +580 -90
- package/build/tools/index.d.ts.map +1 -1
- package/build/tools/index.js +598 -82
- package/build/tools/index.js.map +1 -1
- package/build/tools/validation.d.ts +42 -0
- package/build/tools/validation.d.ts.map +1 -0
- package/build/tools/validation.js +97 -0
- package/build/tools/validation.js.map +1 -0
- package/build/util/diagnose.d.ts +40 -0
- package/build/util/diagnose.d.ts.map +1 -0
- package/build/util/diagnose.js +26 -0
- package/build/util/diagnose.js.map +1 -0
- package/build/util/request-context.d.ts +11 -0
- package/build/util/request-context.d.ts.map +1 -0
- package/build/util/request-context.js +30 -0
- package/build/util/request-context.js.map +1 -0
- package/package.json +2 -1
- package/web/index.html +25 -0
- package/web/styles.css +62 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapshot of session-level state used by `nestr_diagnose`.
|
|
3
|
+
*
|
|
4
|
+
* Built fresh on each tool call (the getter is invoked per-call) so the
|
|
5
|
+
* snapshot reflects the latest session state without the tool handler
|
|
6
|
+
* needing direct access to the SessionData record.
|
|
7
|
+
*/
|
|
8
|
+
export interface DiagnoseSnapshot {
|
|
9
|
+
flow: "A" | "B" | "unknown";
|
|
10
|
+
tokenPresented: boolean;
|
|
11
|
+
tokenFingerprint: string;
|
|
12
|
+
/** Decoded iat/exp from the bearer if it parses as a JWT. `null` for opaque tokens / API keys. */
|
|
13
|
+
tokenAge: {
|
|
14
|
+
iat?: number;
|
|
15
|
+
exp?: number;
|
|
16
|
+
now: number;
|
|
17
|
+
} | null;
|
|
18
|
+
lastUpstream401At?: number;
|
|
19
|
+
lastRefreshAttempt?: {
|
|
20
|
+
at: number;
|
|
21
|
+
success: boolean;
|
|
22
|
+
error?: string;
|
|
23
|
+
};
|
|
24
|
+
sessionCorrelationId?: string;
|
|
25
|
+
hasStoredOAuthSession: boolean;
|
|
26
|
+
isApiKey: boolean;
|
|
27
|
+
mcpClient?: string;
|
|
28
|
+
/** MCP `clientInfo.version` from the initialize handshake. */
|
|
29
|
+
mcpClientVersion?: string;
|
|
30
|
+
userId?: string;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Best-effort JWT decode for nestr_diagnose. Returns null when the token
|
|
34
|
+
* isn't a JWT (e.g., API keys are opaque). Does NOT verify the signature —
|
|
35
|
+
* we just want iat/exp for diagnostics. The check is intentionally narrow:
|
|
36
|
+
* three base64url segments separated by dots, middle segment parses as JSON
|
|
37
|
+
* with at least one of iat/exp.
|
|
38
|
+
*/
|
|
39
|
+
export declare function tryDecodeJwtAge(token: string): DiagnoseSnapshot["tokenAge"];
|
|
40
|
+
//# sourceMappingURL=diagnose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.d.ts","sourceRoot":"","sources":["../../src/util/diagnose.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,GAAG,GAAG,GAAG,GAAG,SAAS,CAAC;IAC5B,cAAc,EAAE,OAAO,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,kGAAkG;IAClG,QAAQ,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7D,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,kBAAkB,CAAC,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,qBAAqB,EAAE,OAAO,CAAC;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,gBAAgB,CAAC,UAAU,CAAC,CAa3E"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best-effort JWT decode for nestr_diagnose. Returns null when the token
|
|
3
|
+
* isn't a JWT (e.g., API keys are opaque). Does NOT verify the signature —
|
|
4
|
+
* we just want iat/exp for diagnostics. The check is intentionally narrow:
|
|
5
|
+
* three base64url segments separated by dots, middle segment parses as JSON
|
|
6
|
+
* with at least one of iat/exp.
|
|
7
|
+
*/
|
|
8
|
+
export function tryDecodeJwtAge(token) {
|
|
9
|
+
const parts = token.split(".");
|
|
10
|
+
if (parts.length !== 3)
|
|
11
|
+
return null;
|
|
12
|
+
try {
|
|
13
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
|
|
14
|
+
if (typeof payload !== "object" || payload === null)
|
|
15
|
+
return null;
|
|
16
|
+
const iat = typeof payload.iat === "number" ? payload.iat : undefined;
|
|
17
|
+
const exp = typeof payload.exp === "number" ? payload.exp : undefined;
|
|
18
|
+
if (iat === undefined && exp === undefined)
|
|
19
|
+
return null;
|
|
20
|
+
return { iat, exp, now: Math.floor(Date.now() / 1000) };
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=diagnose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diagnose.js","sourceRoot":"","sources":["../../src/util/diagnose.ts"],"names":[],"mappings":"AAwBA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QACjF,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC;QACjE,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;QACtE,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACxD,OAAO,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface RequestContext {
|
|
2
|
+
correlationId: string;
|
|
3
|
+
}
|
|
4
|
+
export declare function runWithContext<T>(ctx: RequestContext, fn: () => T): T;
|
|
5
|
+
export declare function getCorrelationId(): string | undefined;
|
|
6
|
+
/**
|
|
7
|
+
* Format a `[cid=...]` log prefix for the current request, or an empty string
|
|
8
|
+
* if there is no active context. Use as: `console.log(`${cidTag()}message`)`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function cidTag(): string;
|
|
11
|
+
//# sourceMappingURL=request-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context.d.ts","sourceRoot":"","sources":["../../src/util/request-context.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,MAAM,CAAC;CACvB;AAID,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,CAAC,CAErE;AAED,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,SAAS,CAErD;AAED;;;GAGG;AACH,wBAAgB,MAAM,IAAI,MAAM,CAG/B"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-scoped context.
|
|
3
|
+
*
|
|
4
|
+
* AsyncLocalStorage carries a per-request `correlationId` through every async
|
|
5
|
+
* call inside `app.post("/mcp", ...)` so log lines emitted by deeply-nested
|
|
6
|
+
* code (NestrClient, OAuth refresh, tool handlers) can be grepped by a single
|
|
7
|
+
* id. The id is also exposed on tool errors so an LLM client can include it
|
|
8
|
+
* in bug reports.
|
|
9
|
+
*
|
|
10
|
+
* Outside a request (e.g., during startup, or in tests that bypass the HTTP
|
|
11
|
+
* layer) `getCorrelationId()` returns `undefined` and callers should treat
|
|
12
|
+
* the absence as "no current request context".
|
|
13
|
+
*/
|
|
14
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
15
|
+
const storage = new AsyncLocalStorage();
|
|
16
|
+
export function runWithContext(ctx, fn) {
|
|
17
|
+
return storage.run(ctx, fn);
|
|
18
|
+
}
|
|
19
|
+
export function getCorrelationId() {
|
|
20
|
+
return storage.getStore()?.correlationId;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Format a `[cid=...]` log prefix for the current request, or an empty string
|
|
24
|
+
* if there is no active context. Use as: `console.log(`${cidTag()}message`)`.
|
|
25
|
+
*/
|
|
26
|
+
export function cidTag() {
|
|
27
|
+
const cid = getCorrelationId();
|
|
28
|
+
return cid ? `[cid=${cid}] ` : "";
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=request-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-context.js","sourceRoot":"","sources":["../../src/util/request-context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAMrD,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAkB,CAAC;AAExD,MAAM,UAAU,cAAc,CAAI,GAAmB,EAAE,EAAW;IAChE,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,OAAO,OAAO,CAAC,QAAQ,EAAE,EAAE,aAAa,CAAC;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,MAAM;IACpB,MAAM,GAAG,GAAG,gBAAgB,EAAE,CAAC;IAC/B,OAAO,GAAG,CAAC,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACpC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nestr/mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.89",
|
|
4
4
|
"mcpName": "io.nestr/mcp",
|
|
5
5
|
"description": "MCP server for Nestr - the platform for self-organizing teams practicing Holacracy, Sociocracy, and role-based work. Manage circles, roles, tactical meetings, governance meetings, tensions, and more.",
|
|
6
6
|
"author": "Nestr <dev@nestr.io>",
|
|
@@ -71,6 +71,7 @@
|
|
|
71
71
|
"express-rate-limit": "^8.3.1",
|
|
72
72
|
"helmet": "^8.1.0",
|
|
73
73
|
"ioredis": "^5.4.0",
|
|
74
|
+
"jimp": "^1.6.1",
|
|
74
75
|
"mcpcat": "^0.1.13",
|
|
75
76
|
"zod": "^3.25.0"
|
|
76
77
|
},
|
package/web/index.html
CHANGED
|
@@ -384,6 +384,12 @@
|
|
|
384
384
|
<p class="tip" style="margin-bottom: 0;">Already set up Nestr as a <strong>Claude.ai connector</strong>? You can reuse it in Claude Code by enabling the flag:<br>
|
|
385
385
|
<code>claude config set --global tengu_claudeai_mcp_connectors true</code><br>
|
|
386
386
|
This makes all your Claude.ai connectors available in Claude Code — no separate MCP setup needed.</p>
|
|
387
|
+
<div class="cli-note">
|
|
388
|
+
<p>Prefer working in the terminal? <a href="https://github.com/nestr-dev/nestr-cli" target="_blank"><code>nestr-cli</code></a> is a complementary option for command-line and agent workflows — install it and drop ready-made Nestr skills straight into Claude Code:</p>
|
|
389
|
+
<pre><code>brew install nestr-dev/tap/nestr-cli <span class="cli-comment"># install the CLI</span>
|
|
390
|
+
npx skills add nestr-dev/nestr-cli <span class="cli-comment"># add the agent skills</span></code></pre>
|
|
391
|
+
<p style="margin-bottom: 0;"><a href="https://github.com/nestr-dev/nestr-cli" target="_blank">Explore nestr-cli →</a></p>
|
|
392
|
+
</div>
|
|
387
393
|
</div>
|
|
388
394
|
|
|
389
395
|
<div class="tab-content" id="cursor">
|
|
@@ -523,6 +529,7 @@
|
|
|
523
529
|
|
|
524
530
|
<div class="tab-content" id="copilot-studio">
|
|
525
531
|
<p class="tip" style="margin-bottom: 16px;">Works with <strong>Microsoft Copilot Studio</strong> agents and <strong>Microsoft 365 Copilot</strong> declarative agents.</p>
|
|
532
|
+
<p class="warning" style="margin-bottom: 16px;"><strong>Keep the Server description under 500 characters.</strong> Copilot Studio's connector backend truncates longer descriptions and surfaces a confusing SQL error (<code>String or binary data would be truncated in table '{0}', column '{1}'</code>) instead of a clear validation message. If a previous save failed with that error, also delete the half-created connector before retrying — Copilot Studio leaves a stub behind that triggers a "display name already exists" error on the next attempt.</p>
|
|
526
533
|
|
|
527
534
|
<div class="config-block hosted oauth active">
|
|
528
535
|
<div class="quickstart-box">
|
|
@@ -974,6 +981,24 @@
|
|
|
974
981
|
</ul>
|
|
975
982
|
</div>
|
|
976
983
|
</div>
|
|
984
|
+
|
|
985
|
+
<div class="cli-cta-box">
|
|
986
|
+
<div class="cli-cta-content">
|
|
987
|
+
<span class="cli-cta-eyebrow">Bonus — prefer the terminal?</span>
|
|
988
|
+
<h3>Add the Nestr CLI</h3>
|
|
989
|
+
<p>
|
|
990
|
+
<code>nestr-cli</code> brings your whole Nestr workspace to the terminal —
|
|
991
|
+
great for quick actions, automation, and AI coding agents.
|
|
992
|
+
</p>
|
|
993
|
+
<pre><code>brew install nestr-dev/tap/nestr-cli <span class="cli-comment"># install the CLI</span>
|
|
994
|
+
npx skills add nestr-dev/nestr-cli <span class="cli-comment"># add the agent skills</span></code></pre>
|
|
995
|
+
<p class="cli-cta-note">
|
|
996
|
+
One Homebrew command to install, one more to drop ready-made Nestr skills into
|
|
997
|
+
Claude Code, Cursor, or Copilot.
|
|
998
|
+
</p>
|
|
999
|
+
<a href="https://github.com/nestr-dev/nestr-cli" target="_blank" class="btn primary">Explore nestr-cli →</a>
|
|
1000
|
+
</div>
|
|
1001
|
+
</div>
|
|
977
1002
|
</div>
|
|
978
1003
|
</section>
|
|
979
1004
|
|
package/web/styles.css
CHANGED
|
@@ -680,6 +680,68 @@ p code, li code {
|
|
|
680
680
|
}
|
|
681
681
|
|
|
682
682
|
/* Tools */
|
|
683
|
+
/* CLI call-to-action — sits inside the Setup section as a bonus step,
|
|
684
|
+
matching the width and card treatment of the numbered steps. */
|
|
685
|
+
.cli-cta-box {
|
|
686
|
+
background: linear-gradient(135deg, #f0f0ff 0%, #fff 100%);
|
|
687
|
+
border: 2px solid var(--primary);
|
|
688
|
+
border-radius: 12px;
|
|
689
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
690
|
+
padding: 32px;
|
|
691
|
+
text-align: center;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
.cli-cta-eyebrow {
|
|
695
|
+
display: inline-block;
|
|
696
|
+
margin-bottom: 8px;
|
|
697
|
+
font-size: 0.8rem;
|
|
698
|
+
font-weight: 600;
|
|
699
|
+
letter-spacing: 0.04em;
|
|
700
|
+
text-transform: uppercase;
|
|
701
|
+
color: var(--primary-dark);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
.cli-cta-box h3 {
|
|
705
|
+
margin-bottom: 12px;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.cli-cta-content > p {
|
|
709
|
+
color: var(--text-muted);
|
|
710
|
+
max-width: 720px;
|
|
711
|
+
margin: 0 auto 16px;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
.cli-cta-box pre {
|
|
715
|
+
max-width: 620px;
|
|
716
|
+
margin: 16px auto;
|
|
717
|
+
text-align: left;
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
.cli-comment {
|
|
721
|
+
color: #94a3b8;
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
.cli-cta-note {
|
|
725
|
+
font-size: 0.95rem;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.cli-cta-box .btn {
|
|
729
|
+
margin-top: 8px;
|
|
730
|
+
}
|
|
731
|
+
|
|
732
|
+
/* CLI note inside the Claude Code setup tab */
|
|
733
|
+
.cli-note {
|
|
734
|
+
margin-top: 16px;
|
|
735
|
+
padding-top: 16px;
|
|
736
|
+
border-top: 1px solid var(--border);
|
|
737
|
+
font-size: 0.9rem;
|
|
738
|
+
color: var(--text-muted);
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
.cli-note pre {
|
|
742
|
+
margin: 12px 0;
|
|
743
|
+
}
|
|
744
|
+
|
|
683
745
|
.tools {
|
|
684
746
|
padding: 60px 0;
|
|
685
747
|
background: var(--secondary);
|