within-sdk 1.0.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 +1 -0
- package/README.md +77 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +243 -0
- package/dist/middleware.d.ts +40 -0
- package/dist/middleware.js +562 -0
- package/dist/modules/compatibility.d.ts +18 -0
- package/dist/modules/compatibility.js +99 -0
- package/dist/modules/constants.d.ts +12 -0
- package/dist/modules/constants.js +12 -0
- package/dist/modules/context-parameters.d.ts +13 -0
- package/dist/modules/context-parameters.js +74 -0
- package/dist/modules/diagnostics.d.ts +7 -0
- package/dist/modules/diagnostics.js +12 -0
- package/dist/modules/eventQueue.d.ts +32 -0
- package/dist/modules/eventQueue.js +234 -0
- package/dist/modules/exceptions.d.ts +13 -0
- package/dist/modules/exceptions.js +730 -0
- package/dist/modules/exporters/datadog.d.ts +17 -0
- package/dist/modules/exporters/datadog.js +166 -0
- package/dist/modules/exporters/otlp.d.ts +13 -0
- package/dist/modules/exporters/otlp.js +140 -0
- package/dist/modules/exporters/posthog.d.ts +32 -0
- package/dist/modules/exporters/posthog.js +272 -0
- package/dist/modules/exporters/sentry.d.ts +27 -0
- package/dist/modules/exporters/sentry.js +386 -0
- package/dist/modules/exporters/trace-context.d.ts +8 -0
- package/dist/modules/exporters/trace-context.js +27 -0
- package/dist/modules/index.d.ts +8 -0
- package/dist/modules/index.js +8 -0
- package/dist/modules/internal.d.ts +33 -0
- package/dist/modules/internal.js +195 -0
- package/dist/modules/logging.d.ts +2 -0
- package/dist/modules/logging.js +74 -0
- package/dist/modules/mcp-sdk-compat.d.ts +32 -0
- package/dist/modules/mcp-sdk-compat.js +111 -0
- package/dist/modules/privacy.d.ts +15 -0
- package/dist/modules/privacy.js +179 -0
- package/dist/modules/redaction.d.ts +11 -0
- package/dist/modules/redaction.js +81 -0
- package/dist/modules/sanitization.d.ts +9 -0
- package/dist/modules/sanitization.js +111 -0
- package/dist/modules/session.d.ts +22 -0
- package/dist/modules/session.js +109 -0
- package/dist/modules/telemetry.d.ts +8 -0
- package/dist/modules/telemetry.js +53 -0
- package/dist/modules/tools.d.ts +25 -0
- package/dist/modules/tools.js +119 -0
- package/dist/modules/tracing.d.ts +4 -0
- package/dist/modules/tracing.js +263 -0
- package/dist/modules/tracingV2.d.ts +2 -0
- package/dist/modules/tracingV2.js +300 -0
- package/dist/modules/truncation.d.ts +24 -0
- package/dist/modules/truncation.js +303 -0
- package/dist/modules/validation.d.ts +6 -0
- package/dist/modules/validation.js +51 -0
- package/dist/network.d.ts +83 -0
- package/dist/network.js +411 -0
- package/dist/proxy.d.ts +31 -0
- package/dist/proxy.js +158 -0
- package/dist/thirdparty/ksuid/base-convert-int-array.js +49 -0
- package/dist/thirdparty/ksuid/base62.js +24 -0
- package/dist/thirdparty/ksuid/index.d.ts +30 -0
- package/dist/thirdparty/ksuid/index.js +201 -0
- package/dist/types.d.ts +197 -0
- package/dist/types.js +5 -0
- package/dist/validate.d.ts +53 -0
- package/dist/validate.js +139 -0
- package/package.json +43 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* With.in MCP Auth SDK — Token Validation
|
|
3
|
+
*
|
|
4
|
+
* Validates tokens against With.in's JWKS endpoint.
|
|
5
|
+
* Caches the JWKS keys in memory with a 5-minute refresh interval.
|
|
6
|
+
*
|
|
7
|
+
* SYNC NOTE: vendor/lib/validate.ts intentionally diverges here — it adds
|
|
8
|
+
* `ngrok-skip-browser-warning` headers for local-dev only. Keep the
|
|
9
|
+
* published SDK clean of those.
|
|
10
|
+
*/
|
|
11
|
+
import type { WithinTokenClaims } from './types.js';
|
|
12
|
+
export declare function validateWithinToken(token: string, jwksUrl: string): Promise<WithinTokenClaims | null>;
|
|
13
|
+
export declare function extractBearerToken(authHeader?: string): string | null;
|
|
14
|
+
/** Report to With.in that the vendor recognises this user as an existing customer.
|
|
15
|
+
* Call this when a With.in token arrives and you find the user in your own DB.
|
|
16
|
+
* With.in will mark the user as a subscriber (no conversion fee).
|
|
17
|
+
*
|
|
18
|
+
* Pass `withinAccessToken` whenever it's available — the backend authenticates
|
|
19
|
+
* the request by checking that token's claims match (email + vendor_slug).
|
|
20
|
+
* Without it the call is rejected, so the vendorTokenValidator path (where
|
|
21
|
+
* no With.in token exists) cannot drive conversions. That path is intentionally
|
|
22
|
+
* niche today; broader auth (vendor shared secret) is planned. */
|
|
23
|
+
export declare function reportConversion(authServerUrl: string, vendorSlug: string, email: string, withinAccessToken?: string): Promise<void>;
|
|
24
|
+
/** Check whether the token holder is now a subscriber for this vendor.
|
|
25
|
+
* Used to unstick users who paid seconds ago but whose cached access
|
|
26
|
+
* token still says the trial is exhausted. Returns false on any error —
|
|
27
|
+
* falling back to the normal trial-exhausted message is the safe default. */
|
|
28
|
+
export declare function checkSubscriptionStatus(authServerUrl: string, token: string): Promise<boolean>;
|
|
29
|
+
export interface ReportToolCallResult {
|
|
30
|
+
/** Backend returned 401 token_revoked — caller must block the tool call.
|
|
31
|
+
* An access token's JWT signature stays valid until its 10-min TTL, so
|
|
32
|
+
* local validation alone can't catch a dashboard-initiated revoke. The
|
|
33
|
+
* /oauth/report roundtrip is the enforcement point. */
|
|
34
|
+
revoked: boolean;
|
|
35
|
+
/** Backend returned 429 tool_budget_exhausted — vendor has configured a
|
|
36
|
+
* per-tool call budget and the user has hit it. Caller must block the
|
|
37
|
+
* tool call so the vendor's handler does NOT run. The user can still
|
|
38
|
+
* call other tools (budgets are per-tool, not global). */
|
|
39
|
+
budgetExhausted?: {
|
|
40
|
+
tool: string;
|
|
41
|
+
limit: number;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Report a tool call back to With.in for lead tracking and revocation
|
|
45
|
+
* enforcement. `aiClient` — the MCP client name captured from the session's
|
|
46
|
+
* `initialize` request (`clientInfo.name`). Lets the vendor and the user
|
|
47
|
+
* see which agent (Claude Desktop, Cursor, ChatGPT, …) actually made
|
|
48
|
+
* the call.
|
|
49
|
+
*
|
|
50
|
+
* Returns `{ revoked: true }` when the backend reports the token has been
|
|
51
|
+
* revoked since issuance. Network/server errors return `{ revoked: false }`
|
|
52
|
+
* so reporting outages never block a tool call. */
|
|
53
|
+
export declare function reportToolCall(authServerUrl: string, token: string, vendorSlug: string, toolName: string, aiClient?: string, toolArguments?: Record<string, unknown> | null): Promise<ReportToolCallResult>;
|
package/dist/validate.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* With.in MCP Auth SDK — Token Validation
|
|
3
|
+
*
|
|
4
|
+
* Validates tokens against With.in's JWKS endpoint.
|
|
5
|
+
* Caches the JWKS keys in memory with a 5-minute refresh interval.
|
|
6
|
+
*
|
|
7
|
+
* SYNC NOTE: vendor/lib/validate.ts intentionally diverges here — it adds
|
|
8
|
+
* `ngrok-skip-browser-warning` headers for local-dev only. Keep the
|
|
9
|
+
* published SDK clean of those.
|
|
10
|
+
*/
|
|
11
|
+
import { createRemoteJWKSet, jwtVerify } from 'jose';
|
|
12
|
+
// Cache JWKS key set per URL
|
|
13
|
+
const jwksCache = new Map();
|
|
14
|
+
function getJwks(jwksUrl) {
|
|
15
|
+
let jwks = jwksCache.get(jwksUrl);
|
|
16
|
+
if (!jwks) {
|
|
17
|
+
jwks = createRemoteJWKSet(new URL(jwksUrl));
|
|
18
|
+
jwksCache.set(jwksUrl, jwks);
|
|
19
|
+
}
|
|
20
|
+
return jwks;
|
|
21
|
+
}
|
|
22
|
+
export async function validateWithinToken(token, jwksUrl) {
|
|
23
|
+
try {
|
|
24
|
+
const jwks = getJwks(jwksUrl);
|
|
25
|
+
const { payload } = await jwtVerify(token, jwks);
|
|
26
|
+
// Verify it's a With.in token
|
|
27
|
+
if (payload.token_type !== 'access' && payload.token_type !== 'identity') {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return payload;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function extractBearerToken(authHeader) {
|
|
37
|
+
if (!authHeader)
|
|
38
|
+
return null;
|
|
39
|
+
const match = authHeader.match(/^Bearer\s+(.+)$/i);
|
|
40
|
+
return match?.[1] ?? null;
|
|
41
|
+
}
|
|
42
|
+
/** Report to With.in that the vendor recognises this user as an existing customer.
|
|
43
|
+
* Call this when a With.in token arrives and you find the user in your own DB.
|
|
44
|
+
* With.in will mark the user as a subscriber (no conversion fee).
|
|
45
|
+
*
|
|
46
|
+
* Pass `withinAccessToken` whenever it's available — the backend authenticates
|
|
47
|
+
* the request by checking that token's claims match (email + vendor_slug).
|
|
48
|
+
* Without it the call is rejected, so the vendorTokenValidator path (where
|
|
49
|
+
* no With.in token exists) cannot drive conversions. That path is intentionally
|
|
50
|
+
* niche today; broader auth (vendor shared secret) is planned. */
|
|
51
|
+
export async function reportConversion(authServerUrl, vendorSlug, email, withinAccessToken) {
|
|
52
|
+
if (!withinAccessToken)
|
|
53
|
+
return; // No token, no auth → skip silently.
|
|
54
|
+
try {
|
|
55
|
+
await fetch(`${authServerUrl}/oauth/conversion`, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
headers: {
|
|
58
|
+
'Content-Type': 'application/json',
|
|
59
|
+
Authorization: `Bearer ${withinAccessToken}`,
|
|
60
|
+
},
|
|
61
|
+
body: JSON.stringify({ email, vendor_slug: vendorSlug }),
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Don't block auth if reporting fails
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/** Check whether the token holder is now a subscriber for this vendor.
|
|
69
|
+
* Used to unstick users who paid seconds ago but whose cached access
|
|
70
|
+
* token still says the trial is exhausted. Returns false on any error —
|
|
71
|
+
* falling back to the normal trial-exhausted message is the safe default. */
|
|
72
|
+
export async function checkSubscriptionStatus(authServerUrl, token) {
|
|
73
|
+
// Hard-cap the live check so a slow or dead auth server doesn't stall the
|
|
74
|
+
// tool response. Claude will time out the tool call around ~30s; we fail
|
|
75
|
+
// fast at 3s and let the normal trial-ended message render.
|
|
76
|
+
const controller = new AbortController();
|
|
77
|
+
const timer = setTimeout(() => controller.abort(), 3000);
|
|
78
|
+
try {
|
|
79
|
+
const res = await fetch(`${authServerUrl}/oauth/subscription-status`, {
|
|
80
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
81
|
+
signal: controller.signal,
|
|
82
|
+
});
|
|
83
|
+
if (!res.ok)
|
|
84
|
+
return false;
|
|
85
|
+
const data = await res.json();
|
|
86
|
+
return data.subscriber === true;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Report a tool call back to With.in for lead tracking and revocation
|
|
96
|
+
* enforcement. `aiClient` — the MCP client name captured from the session's
|
|
97
|
+
* `initialize` request (`clientInfo.name`). Lets the vendor and the user
|
|
98
|
+
* see which agent (Claude Desktop, Cursor, ChatGPT, …) actually made
|
|
99
|
+
* the call.
|
|
100
|
+
*
|
|
101
|
+
* Returns `{ revoked: true }` when the backend reports the token has been
|
|
102
|
+
* revoked since issuance. Network/server errors return `{ revoked: false }`
|
|
103
|
+
* so reporting outages never block a tool call. */
|
|
104
|
+
export async function reportToolCall(authServerUrl, token, vendorSlug, toolName, aiClient, toolArguments) {
|
|
105
|
+
try {
|
|
106
|
+
const res = await fetch(`${authServerUrl}/oauth/report`, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: { 'Content-Type': 'application/json' },
|
|
109
|
+
body: JSON.stringify({
|
|
110
|
+
token,
|
|
111
|
+
tool_name: toolName,
|
|
112
|
+
vendor_slug: vendorSlug,
|
|
113
|
+
ai_client: aiClient,
|
|
114
|
+
tool_arguments: toolArguments ?? undefined,
|
|
115
|
+
}),
|
|
116
|
+
});
|
|
117
|
+
if (res.status === 401) {
|
|
118
|
+
try {
|
|
119
|
+
const body = (await res.json());
|
|
120
|
+
if (body?.error === 'token_revoked')
|
|
121
|
+
return { revoked: true };
|
|
122
|
+
}
|
|
123
|
+
catch { }
|
|
124
|
+
}
|
|
125
|
+
if (res.status === 429) {
|
|
126
|
+
try {
|
|
127
|
+
const body = (await res.json());
|
|
128
|
+
if (body?.error === 'tool_budget_exhausted' && typeof body.tool === 'string' && typeof body.limit === 'number') {
|
|
129
|
+
return { revoked: false, budgetExhausted: { tool: body.tool, limit: body.limit } };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
catch { }
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
// Don't block tool calls if reporting fails
|
|
137
|
+
}
|
|
138
|
+
return { revoked: false };
|
|
139
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "within-sdk",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Within SDK for MCP analytics, workflow intelligence, and qualified opportunities.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"mcp",
|
|
21
|
+
"model-context-protocol",
|
|
22
|
+
"within",
|
|
23
|
+
"sdk",
|
|
24
|
+
"workflow",
|
|
25
|
+
"qualification"
|
|
26
|
+
],
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"homepage": "https://getwith.in",
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsc -p tsconfig.json && rm -rf dist/thirdparty && cp -R src/thirdparty dist/thirdparty",
|
|
31
|
+
"prepublishOnly": "npm run build",
|
|
32
|
+
"test": "tsx --test src/*.test.ts"
|
|
33
|
+
},
|
|
34
|
+
"peerDependencies": {
|
|
35
|
+
"@modelcontextprotocol/sdk": ">=1.11"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@modelcontextprotocol/sdk": "~1.24.2",
|
|
39
|
+
"@types/node": "^25.5.0",
|
|
40
|
+
"tsx": "^4.21.0",
|
|
41
|
+
"typescript": "^6.0.2"
|
|
42
|
+
}
|
|
43
|
+
}
|