@privos_ai/app-server 0.1.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 +21 -0
- package/README.md +90 -0
- package/dist/app-descriptor.d.ts +39 -0
- package/dist/app-descriptor.d.ts.map +1 -0
- package/dist/app-descriptor.js +71 -0
- package/dist/app-descriptor.js.map +1 -0
- package/dist/auth/user-token.d.ts +44 -0
- package/dist/auth/user-token.d.ts.map +1 -0
- package/dist/auth/user-token.js +108 -0
- package/dist/auth/user-token.js.map +1 -0
- package/dist/context/identity-assertions.d.ts +18 -0
- package/dist/context/identity-assertions.d.ts.map +1 -0
- package/dist/context/identity-assertions.js +37 -0
- package/dist/context/identity-assertions.js.map +1 -0
- package/dist/context/identity-mode.d.ts +3 -0
- package/dist/context/identity-mode.d.ts.map +1 -0
- package/dist/context/identity-mode.js +6 -0
- package/dist/context/identity-mode.js.map +1 -0
- package/dist/context/tool-call-context.d.ts +29 -0
- package/dist/context/tool-call-context.d.ts.map +1 -0
- package/dist/context/tool-call-context.js +2 -0
- package/dist/context/tool-call-context.js.map +1 -0
- package/dist/direct/express-router.d.ts +35 -0
- package/dist/direct/express-router.d.ts.map +1 -0
- package/dist/direct/express-router.js +148 -0
- package/dist/direct/express-router.js.map +1 -0
- package/dist/direct/http-ingress.d.ts +84 -0
- package/dist/direct/http-ingress.d.ts.map +1 -0
- package/dist/direct/http-ingress.js +124 -0
- package/dist/direct/http-ingress.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/protocol/dispatch.d.ts +7 -0
- package/dist/protocol/dispatch.d.ts.map +1 -0
- package/dist/protocol/dispatch.js +78 -0
- package/dist/protocol/dispatch.js.map +1 -0
- package/dist/protocol/errors.d.ts +16 -0
- package/dist/protocol/errors.d.ts.map +1 -0
- package/dist/protocol/errors.js +84 -0
- package/dist/protocol/errors.js.map +1 -0
- package/dist/protocol/logging.d.ts +16 -0
- package/dist/protocol/logging.d.ts.map +1 -0
- package/dist/protocol/logging.js +18 -0
- package/dist/protocol/logging.js.map +1 -0
- package/dist/protocol/types.d.ts +54 -0
- package/dist/protocol/types.d.ts.map +1 -0
- package/dist/protocol/types.js +7 -0
- package/dist/protocol/types.js.map +1 -0
- package/dist/relay/message-adapter.d.ts +9 -0
- package/dist/relay/message-adapter.d.ts.map +1 -0
- package/dist/relay/message-adapter.js +32 -0
- package/dist/relay/message-adapter.js.map +1 -0
- package/dist/relay/relay-client.d.ts +63 -0
- package/dist/relay/relay-client.d.ts.map +1 -0
- package/dist/relay/relay-client.js +447 -0
- package/dist/relay/relay-client.js.map +1 -0
- package/dist/runtime.d.ts +104 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +351 -0
- package/dist/runtime.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import express from 'express';
|
|
3
|
+
import { buildManifestJson, } from '../app-descriptor.js';
|
|
4
|
+
import { INVALID_REQUEST, PARSE_ERROR, errorResponse, jsonRpcError, } from '../protocol/errors.js';
|
|
5
|
+
import { AppServerRuntime, DEFAULT_MAX_MESSAGE_BYTES, ephemeralSessionScope, extractDirectCallerCredential, resolveCallerCredential, } from '../runtime.js';
|
|
6
|
+
const REQUIRED_CORS_HEADERS = [
|
|
7
|
+
'Content-Type',
|
|
8
|
+
'Authorization',
|
|
9
|
+
'X-MCP-User-Id',
|
|
10
|
+
'Mcp-Session-Id',
|
|
11
|
+
'MCP-Protocol-Version',
|
|
12
|
+
];
|
|
13
|
+
/**
|
|
14
|
+
* Composable Express Router for Direct MCP transport.
|
|
15
|
+
* Mount with `app.use(createDirectRouter(opts))` — does not create or listen on an app,
|
|
16
|
+
* and does not own `/ui`, health, ready, or register routes.
|
|
17
|
+
*/
|
|
18
|
+
export function createDirectRouter(options) {
|
|
19
|
+
const runtime = options.runtime ??
|
|
20
|
+
new AppServerRuntime({
|
|
21
|
+
descriptor: options.descriptor,
|
|
22
|
+
handler: options.handler,
|
|
23
|
+
ui: options.ui,
|
|
24
|
+
auth: options.auth,
|
|
25
|
+
mapAppError: options.mapAppError,
|
|
26
|
+
limits: options.limits,
|
|
27
|
+
logger: options.logger,
|
|
28
|
+
});
|
|
29
|
+
const mcpPath = options.mcpPath ?? '/mcp';
|
|
30
|
+
const manifestPath = options.manifestPath ?? '/.well-known/mcp/manifest.json';
|
|
31
|
+
const allowHeaders = mergeCorsHeaders(options.corsAllowHeaders);
|
|
32
|
+
const maxBytes = runtime.getLimits().maxMessageBytes || DEFAULT_MAX_MESSAGE_BYTES;
|
|
33
|
+
const router = Router();
|
|
34
|
+
router.use((req, res, next) => {
|
|
35
|
+
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
36
|
+
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
|
37
|
+
res.setHeader('Access-Control-Allow-Headers', allowHeaders.join(', '));
|
|
38
|
+
if (req.method === 'OPTIONS') {
|
|
39
|
+
res.status(204).end();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
next();
|
|
43
|
+
});
|
|
44
|
+
router.get(manifestPath, async (_req, res, next) => {
|
|
45
|
+
try {
|
|
46
|
+
const descriptor = await runtime.resolveDescriptor();
|
|
47
|
+
res.json(buildManifestJson(descriptor));
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
next(err);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
router.post(mcpPath, express.json({
|
|
54
|
+
limit: maxBytes,
|
|
55
|
+
type: 'application/json',
|
|
56
|
+
}), async (req, res, next) => {
|
|
57
|
+
try {
|
|
58
|
+
await handleMcpPost(req, res, runtime, options);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
next(err);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Body errors on MCP path → stable JSON-RPC (+ HTTP status for oversize).
|
|
65
|
+
router.use((err, req, res, next) => {
|
|
66
|
+
if (!isMcpPath(req, mcpPath)) {
|
|
67
|
+
next(err);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
if (isBodyTooLargeError(err)) {
|
|
71
|
+
res.status(413).json(errorResponse(null, jsonRpcError(INVALID_REQUEST, 'Request too large', {
|
|
72
|
+
code: 'REQUEST_TOO_LARGE',
|
|
73
|
+
})));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (isBodyParseError(err)) {
|
|
77
|
+
res.status(200).json(errorResponse(null, jsonRpcError(PARSE_ERROR, 'Parse error')));
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
next(err);
|
|
81
|
+
});
|
|
82
|
+
return router;
|
|
83
|
+
}
|
|
84
|
+
async function handleMcpPost(req, res, runtime, options) {
|
|
85
|
+
const extract = options.extractCallerCredential ??
|
|
86
|
+
((ingress) => extractDirectCallerCredential(ingress.headers));
|
|
87
|
+
const credentialResolution = await resolveCallerCredential(extract, {
|
|
88
|
+
headers: req.headers,
|
|
89
|
+
});
|
|
90
|
+
const body = req.body;
|
|
91
|
+
const requestId = body && typeof body === 'object' && Object.prototype.hasOwnProperty.call(body, 'id')
|
|
92
|
+
? body.id
|
|
93
|
+
: undefined;
|
|
94
|
+
const sessionHeader = headerValue(req.headers['mcp-session-id']);
|
|
95
|
+
const sessionScope = sessionHeader?.trim()
|
|
96
|
+
? `mcp-session:${sessionHeader.trim()}`
|
|
97
|
+
: ephemeralSessionScope('direct');
|
|
98
|
+
const context = await runtime.buildContext({
|
|
99
|
+
transport: 'direct',
|
|
100
|
+
requestId,
|
|
101
|
+
sessionScope,
|
|
102
|
+
credentialResolution,
|
|
103
|
+
});
|
|
104
|
+
const outcome = await runtime.dispatchObject(body, context);
|
|
105
|
+
if (outcome.type === 'no_response' || outcome.type === 'protocol_warning') {
|
|
106
|
+
res.status(202).end();
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
res.status(200).json(outcome.response);
|
|
110
|
+
}
|
|
111
|
+
function isMcpPath(req, mcpPath) {
|
|
112
|
+
const path = req.path || req.url?.split('?')[0] || '';
|
|
113
|
+
return path === mcpPath || path.endsWith(mcpPath);
|
|
114
|
+
}
|
|
115
|
+
function isBodyParseError(err) {
|
|
116
|
+
if (!err || typeof err !== 'object')
|
|
117
|
+
return false;
|
|
118
|
+
const e = err;
|
|
119
|
+
return (e.type === 'entity.parse.failed' ||
|
|
120
|
+
e.name === 'SyntaxError' ||
|
|
121
|
+
((e.status === 400 || e.statusCode === 400) && e.type !== 'entity.too.large'));
|
|
122
|
+
}
|
|
123
|
+
function isBodyTooLargeError(err) {
|
|
124
|
+
if (!err || typeof err !== 'object')
|
|
125
|
+
return false;
|
|
126
|
+
const e = err;
|
|
127
|
+
return (e.type === 'entity.too.large' ||
|
|
128
|
+
e.status === 413 ||
|
|
129
|
+
e.statusCode === 413);
|
|
130
|
+
}
|
|
131
|
+
function headerValue(value) {
|
|
132
|
+
if (Array.isArray(value))
|
|
133
|
+
return value[0];
|
|
134
|
+
return value;
|
|
135
|
+
}
|
|
136
|
+
function mergeCorsHeaders(extra) {
|
|
137
|
+
const set = new Set(REQUIRED_CORS_HEADERS.map((h) => h.toLowerCase()));
|
|
138
|
+
const ordered = [...REQUIRED_CORS_HEADERS];
|
|
139
|
+
for (const h of extra ?? []) {
|
|
140
|
+
if (!set.has(h.toLowerCase())) {
|
|
141
|
+
set.add(h.toLowerCase());
|
|
142
|
+
ordered.push(h);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return ordered;
|
|
146
|
+
}
|
|
147
|
+
export { AppServerRuntime, extractDirectCallerCredential };
|
|
148
|
+
//# sourceMappingURL=express-router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"express-router.js","sourceRoot":"","sources":["../../src/direct/express-router.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience HTTP server around `createDirectRouter` for apps that want a
|
|
3
|
+
* single listen (e.g. Relay process also exposing Direct MCP, or a minimal
|
|
4
|
+
* Direct-only binary) without hand-rolling Express health/ready/listen.
|
|
5
|
+
*
|
|
6
|
+
* Does not own `/ui`, register, or app-specific webhooks — mount those on the
|
|
7
|
+
* returned `app` before `startHttpIngress`, or use `createHttpIngressApp` and
|
|
8
|
+
* call `listen` yourself.
|
|
9
|
+
*/
|
|
10
|
+
import { type Express, type Request } from 'express';
|
|
11
|
+
import type { Server } from 'node:http';
|
|
12
|
+
import { type DirectRouterOptions } from './express-router.js';
|
|
13
|
+
export type ReadinessCheckResult = {
|
|
14
|
+
ok: boolean;
|
|
15
|
+
/** HTTP status when not ok; default 503. */
|
|
16
|
+
status?: number;
|
|
17
|
+
/** JSON body (merged with `{ ok, status: 'ready'|'not_ready' }` if those keys absent). */
|
|
18
|
+
body?: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
export interface HttpIngressAppOptions extends DirectRouterOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Liveness probe. Default `{ path: '/health' }`.
|
|
23
|
+
* Set `false` to omit (app mounts its own).
|
|
24
|
+
*/
|
|
25
|
+
health?: false | {
|
|
26
|
+
path?: string;
|
|
27
|
+
/** Extra fields merged into `{ ok: true, status: 'alive' }`. */
|
|
28
|
+
body?: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Readiness probe. Omit to skip `/ready`.
|
|
32
|
+
* `check` is app-owned (DB, pool, secrets) — runtime stays business-agnostic.
|
|
33
|
+
*/
|
|
34
|
+
ready?: {
|
|
35
|
+
path?: string;
|
|
36
|
+
check: (req: Request) => ReadinessCheckResult | Promise<ReadinessCheckResult>;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
export interface HttpIngressListenOptions extends HttpIngressAppOptions {
|
|
40
|
+
port: number;
|
|
41
|
+
host?: string;
|
|
42
|
+
/** Used in startup logs; default `http://localhost:${port}`. */
|
|
43
|
+
publicUrl?: string;
|
|
44
|
+
/** Prefix for default console logging when `logger` is unset. */
|
|
45
|
+
logPrefix?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Mount app-owned routes (/ui, /public, register stubs, webhooks) after the
|
|
48
|
+
* ingress app is built and before listen. May be async (e.g. Vite middleware).
|
|
49
|
+
*/
|
|
50
|
+
configure?: (app: Express) => void | Promise<void>;
|
|
51
|
+
}
|
|
52
|
+
export interface HttpIngressHandle {
|
|
53
|
+
app: Express;
|
|
54
|
+
server: Server;
|
|
55
|
+
port: number;
|
|
56
|
+
publicUrl: string;
|
|
57
|
+
close(): Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Build an Express app with optional /health + /ready and `createDirectRouter`.
|
|
61
|
+
* Does not listen.
|
|
62
|
+
*/
|
|
63
|
+
export declare function createHttpIngressApp(options: HttpIngressAppOptions): Express;
|
|
64
|
+
/**
|
|
65
|
+
* `createHttpIngressApp` + optional `configure` + `listen`. Returns a handle with `close()`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function startHttpIngress(options: HttpIngressListenOptions): Promise<HttpIngressHandle>;
|
|
68
|
+
export type ResolveHttpIngressListenOptions = {
|
|
69
|
+
/** Used when HTTP_PORT / PORT are unset. Default 8080. */
|
|
70
|
+
defaultPort?: number;
|
|
71
|
+
env?: NodeJS.ProcessEnv;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Resolve listen config from env (shared by Relay+HTTP dual mode and Direct apps).
|
|
75
|
+
* Disabled when `HTTP_INGRESS` is 0/false/off, or resolved port ≤ 0.
|
|
76
|
+
*
|
|
77
|
+
* Env: `HTTP_INGRESS`, `HTTP_PORT` (preferred), `PORT`, `PUBLIC_URL`.
|
|
78
|
+
*/
|
|
79
|
+
export declare function resolveHttpIngressListen(options?: ResolveHttpIngressListenOptions): {
|
|
80
|
+
enabled: boolean;
|
|
81
|
+
port: number;
|
|
82
|
+
publicUrl: string;
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=http-ingress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-ingress.d.ts","sourceRoot":"","sources":["../../src/direct/http-ingress.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAgB,EAAE,KAAK,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAsB,KAAK,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,MAAM,MAAM,oBAAoB,GAAG;IAClC,EAAE,EAAE,OAAO,CAAC;IACZ,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,0FAA0F;IAC1F,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF,MAAM,WAAW,qBAAsB,SAAQ,mBAAmB;IACjE;;;OAGG;IACH,MAAM,CAAC,EACJ,KAAK,GACL;QACA,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gEAAgE;QAChE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC9B,CAAC;IACL;;;OAGG;IACH,KAAK,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,oBAAoB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;KAC9E,CAAC;CACF;AAED,MAAM,WAAW,wBAAyB,SAAQ,qBAAqB;IACtE,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACnD;AAED,MAAM,WAAW,iBAAiB;IACjC,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAsC5E;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CACrC,OAAO,EAAE,wBAAwB,GAC/B,OAAO,CAAC,iBAAiB,CAAC,CA4D5B;AAED,MAAM,MAAM,+BAA+B,GAAG;IAC7C,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CACxB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,wBAAwB,CACvC,OAAO,GAAE,+BAAoC,GAC3C;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAiBvD"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience HTTP server around `createDirectRouter` for apps that want a
|
|
3
|
+
* single listen (e.g. Relay process also exposing Direct MCP, or a minimal
|
|
4
|
+
* Direct-only binary) without hand-rolling Express health/ready/listen.
|
|
5
|
+
*
|
|
6
|
+
* Does not own `/ui`, register, or app-specific webhooks — mount those on the
|
|
7
|
+
* returned `app` before `startHttpIngress`, or use `createHttpIngressApp` and
|
|
8
|
+
* call `listen` yourself.
|
|
9
|
+
*/
|
|
10
|
+
import express from 'express';
|
|
11
|
+
import { createDirectRouter } from './express-router.js';
|
|
12
|
+
/**
|
|
13
|
+
* Build an Express app with optional /health + /ready and `createDirectRouter`.
|
|
14
|
+
* Does not listen.
|
|
15
|
+
*/
|
|
16
|
+
export function createHttpIngressApp(options) {
|
|
17
|
+
const app = express();
|
|
18
|
+
if (options.health !== false) {
|
|
19
|
+
const path = options.health?.path ?? '/health';
|
|
20
|
+
const extra = options.health?.body ?? {};
|
|
21
|
+
app.get(path, (_req, res) => {
|
|
22
|
+
res.status(200).json({ ok: true, status: 'alive', ...extra });
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
if (options.ready) {
|
|
26
|
+
const path = options.ready.path ?? '/ready';
|
|
27
|
+
const check = options.ready.check;
|
|
28
|
+
app.get(path, async (req, res, next) => {
|
|
29
|
+
try {
|
|
30
|
+
const result = await check(req);
|
|
31
|
+
const status = result.ok ? 200 : (result.status ?? 503);
|
|
32
|
+
const body = {
|
|
33
|
+
ok: result.ok,
|
|
34
|
+
status: result.ok ? 'ready' : 'not_ready',
|
|
35
|
+
...(result.body ?? {}),
|
|
36
|
+
};
|
|
37
|
+
res.status(status).json(body);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
next(err);
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
const { health: _h, ready: _r, ...routerOpts } = options;
|
|
45
|
+
app.use(createDirectRouter(routerOpts));
|
|
46
|
+
return app;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* `createHttpIngressApp` + optional `configure` + `listen`. Returns a handle with `close()`.
|
|
50
|
+
*/
|
|
51
|
+
export async function startHttpIngress(options) {
|
|
52
|
+
const logPrefix = options.logPrefix ?? '[HttpIngress]';
|
|
53
|
+
const { configure, port, host, publicUrl, logPrefix: _lp, ...ingressAppOptions } = options;
|
|
54
|
+
const logger = ingressAppOptions.logger ??
|
|
55
|
+
((event, fields) => {
|
|
56
|
+
const method = typeof fields.method === 'string' ? fields.method : undefined;
|
|
57
|
+
const toolName = typeof fields.toolName === 'string' ? fields.toolName : undefined;
|
|
58
|
+
const label = method === 'tools/call' && toolName
|
|
59
|
+
? `tools/call ${toolName}`
|
|
60
|
+
: (method ?? event);
|
|
61
|
+
if (event.includes('error') || event.includes('fail') || event.includes('backpressure')) {
|
|
62
|
+
console.error(`${logPrefix} ✗ ${event} ${label}`, JSON.stringify(fields).slice(0, 400));
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
console.log(`${logPrefix} · ${event} ${label}`);
|
|
66
|
+
});
|
|
67
|
+
const app = createHttpIngressApp({ ...ingressAppOptions, logger });
|
|
68
|
+
if (configure)
|
|
69
|
+
await configure(app);
|
|
70
|
+
return new Promise((resolve, reject) => {
|
|
71
|
+
const server = host
|
|
72
|
+
? app.listen(port, host, onListening)
|
|
73
|
+
: app.listen(port, onListening);
|
|
74
|
+
function onListening() {
|
|
75
|
+
const addr = server.address();
|
|
76
|
+
const boundPort = typeof addr === 'object' && addr && typeof addr.port === 'number'
|
|
77
|
+
? addr.port
|
|
78
|
+
: port;
|
|
79
|
+
const boundPublicUrl = publicUrl?.replace(/\/$/, '') ||
|
|
80
|
+
`http://localhost:${boundPort}`;
|
|
81
|
+
const mcpPath = options.mcpPath ?? '/mcp';
|
|
82
|
+
const manifestPath = options.manifestPath ?? '/.well-known/mcp/manifest.json';
|
|
83
|
+
console.log(`${logPrefix} Listening on ${boundPublicUrl} (port ${boundPort})`);
|
|
84
|
+
console.log(`${logPrefix} MCP: ${boundPublicUrl}${mcpPath}`);
|
|
85
|
+
console.log(`${logPrefix} Manifest: ${boundPublicUrl}${manifestPath}`);
|
|
86
|
+
if (options.health !== false) {
|
|
87
|
+
const healthPath = options.health?.path ?? '/health';
|
|
88
|
+
console.log(`${logPrefix} Health: ${boundPublicUrl}${healthPath}`);
|
|
89
|
+
}
|
|
90
|
+
resolve({
|
|
91
|
+
app,
|
|
92
|
+
server,
|
|
93
|
+
port: boundPort,
|
|
94
|
+
publicUrl: boundPublicUrl,
|
|
95
|
+
close: () => new Promise((res, rej) => {
|
|
96
|
+
server.close((err) => (err ? rej(err) : res()));
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
server.on('error', reject);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolve listen config from env (shared by Relay+HTTP dual mode and Direct apps).
|
|
105
|
+
* Disabled when `HTTP_INGRESS` is 0/false/off, or resolved port ≤ 0.
|
|
106
|
+
*
|
|
107
|
+
* Env: `HTTP_INGRESS`, `HTTP_PORT` (preferred), `PORT`, `PUBLIC_URL`.
|
|
108
|
+
*/
|
|
109
|
+
export function resolveHttpIngressListen(options = {}) {
|
|
110
|
+
const env = options.env ?? process.env;
|
|
111
|
+
const defaultPort = options.defaultPort ?? 8080;
|
|
112
|
+
const flag = env.HTTP_INGRESS?.trim().toLowerCase();
|
|
113
|
+
if (flag === '0' || flag === 'false' || flag === 'off') {
|
|
114
|
+
return { enabled: false, port: 0, publicUrl: '' };
|
|
115
|
+
}
|
|
116
|
+
const rawPort = env.HTTP_PORT?.trim() || env.PORT?.trim() || String(defaultPort);
|
|
117
|
+
const port = Number.parseInt(rawPort, 10);
|
|
118
|
+
if (!Number.isFinite(port) || port <= 0) {
|
|
119
|
+
return { enabled: false, port: 0, publicUrl: '' };
|
|
120
|
+
}
|
|
121
|
+
const publicUrl = (env.PUBLIC_URL || `http://localhost:${port}`).replace(/\/$/, '');
|
|
122
|
+
return { enabled: true, port, publicUrl };
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=http-ingress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-ingress.js","sourceRoot":"","sources":["../../src/direct/http-ingress.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export { MCP_PROTOCOL_VERSION, MCP_UI_MIME } from './app-descriptor.js';
|
|
2
|
+
export type { AppDescriptor } from './app-descriptor.js';
|
|
3
|
+
export { buildInitializeResult, buildManifestJson, buildPairingMetadata, validateDescriptorCapabilities, } from './app-descriptor.js';
|
|
4
|
+
export type { VerifiedActor, IdentityState, ToolCallContext, } from './context/tool-call-context.js';
|
|
5
|
+
export type { IdentityEnforcementMode } from './context/identity-mode.js';
|
|
6
|
+
export { parseIdentityEnforcementMode } from './context/identity-mode.js';
|
|
7
|
+
export { IdentityAssertionError, assertActorAvailable, assertActorMatchesLegacyId, } from './context/identity-assertions.js';
|
|
8
|
+
export type { AuthOptions, CallerCredential, VerifyUserTokenResult, } from './auth/user-token.js';
|
|
9
|
+
export { verifyUserToken, verifyPrivosUser, clearJwksCache, } from './auth/user-token.js';
|
|
10
|
+
export type { JsonRpcId, JsonRpcErrorObject, McpRequest, McpNotification, McpResponse, ApplicationMcpRequest, ApplicationMcpMethod, } from './protocol/types.js';
|
|
11
|
+
export { PARSE_ERROR, INVALID_REQUEST, METHOD_NOT_FOUND, INVALID_PARAMS, INTERNAL_ERROR, SERVER_BUSY, jsonRpcError, normalizeThrownError, } from './protocol/errors.js';
|
|
12
|
+
export { parseJsonRpcMessage, parseJsonText, isMcpNotificationMethod, } from './protocol/dispatch.js';
|
|
13
|
+
export type { AppMcpHandler, AppErrorMapper, CallerCredentialExtractor, CallerCredentialResolution, UiResourceProvider, RuntimeLimits, AppServerRuntimeOptions, DispatchOutcome, RelayCallerAuthSurface, } from './runtime.js';
|
|
14
|
+
export { AppServerRuntime, DEFAULT_MAX_MESSAGE_BYTES, DEFAULT_MAX_BUFFERED_BYTES, encodeInFlightId, extractDirectCallerCredential, relayCallerAuthSurface, resolveCallerCredential, ephemeralSessionScope, } from './runtime.js';
|
|
15
|
+
export { createDirectRouter } from './direct/express-router.js';
|
|
16
|
+
export type { DirectRouterOptions } from './direct/express-router.js';
|
|
17
|
+
export { createHttpIngressApp, startHttpIngress, resolveHttpIngressListen, } from './direct/http-ingress.js';
|
|
18
|
+
export type { HttpIngressAppOptions, HttpIngressListenOptions, HttpIngressHandle, ReadinessCheckResult, ResolveHttpIngressListenOptions, } from './direct/http-ingress.js';
|
|
19
|
+
export { pairOverWebSocket, pairFromDescriptor, connectRelay, } from './relay/relay-client.js';
|
|
20
|
+
export type { PairAppMeta, PairingResult, RelayClientOptions, RelayHandle, } from './relay/relay-client.js';
|
|
21
|
+
export { rawDataToText, MessageTooLargeError } from './relay/message-adapter.js';
|
|
22
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACxE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EACN,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,8BAA8B,GAC9B,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EACX,aAAa,EACb,aAAa,EACb,eAAe,GACf,MAAM,gCAAgC,CAAC;AACxC,YAAY,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,0BAA0B,GAC1B,MAAM,kCAAkC,CAAC;AAE1C,YAAY,EACX,WAAW,EACX,gBAAgB,EAChB,qBAAqB,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,cAAc,GACd,MAAM,sBAAsB,CAAC;AAE9B,YAAY,EACX,SAAS,EACT,kBAAkB,EAClB,UAAU,EACV,eAAe,EACf,WAAW,EACX,qBAAqB,EACrB,oBAAoB,GACpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,WAAW,EACX,YAAY,EACZ,oBAAoB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EACX,aAAa,EACb,cAAc,EACd,yBAAyB,EACzB,0BAA0B,EAC1B,kBAAkB,EAClB,aAAa,EACb,uBAAuB,EACvB,eAAe,EACf,sBAAsB,GACtB,MAAM,cAAc,CAAC;AACtB,OAAO,EACN,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,EAChB,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,YAAY,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,OAAO,EACN,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,GACxB,MAAM,0BAA0B,CAAC;AAClC,YAAY,EACX,qBAAqB,EACrB,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,+BAA+B,GAC/B,MAAM,0BAA0B,CAAC;AAElC,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,GACZ,MAAM,yBAAyB,CAAC;AACjC,YAAY,EACX,WAAW,EACX,aAAa,EACb,kBAAkB,EAClB,WAAW,GACX,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { MCP_PROTOCOL_VERSION, MCP_UI_MIME } from './app-descriptor.js';
|
|
2
|
+
export { buildInitializeResult, buildManifestJson, buildPairingMetadata, validateDescriptorCapabilities, } from './app-descriptor.js';
|
|
3
|
+
export { parseIdentityEnforcementMode } from './context/identity-mode.js';
|
|
4
|
+
export { IdentityAssertionError, assertActorAvailable, assertActorMatchesLegacyId, } from './context/identity-assertions.js';
|
|
5
|
+
export { verifyUserToken, verifyPrivosUser, clearJwksCache, } from './auth/user-token.js';
|
|
6
|
+
export { PARSE_ERROR, INVALID_REQUEST, METHOD_NOT_FOUND, INVALID_PARAMS, INTERNAL_ERROR, SERVER_BUSY, jsonRpcError, normalizeThrownError, } from './protocol/errors.js';
|
|
7
|
+
export { parseJsonRpcMessage, parseJsonText, isMcpNotificationMethod, } from './protocol/dispatch.js';
|
|
8
|
+
export { AppServerRuntime, DEFAULT_MAX_MESSAGE_BYTES, DEFAULT_MAX_BUFFERED_BYTES, encodeInFlightId, extractDirectCallerCredential, relayCallerAuthSurface, resolveCallerCredential, ephemeralSessionScope, } from './runtime.js';
|
|
9
|
+
export { createDirectRouter } from './direct/express-router.js';
|
|
10
|
+
export { createHttpIngressApp, startHttpIngress, resolveHttpIngressListen, } from './direct/http-ingress.js';
|
|
11
|
+
export { pairOverWebSocket, pairFromDescriptor, connectRelay, } from './relay/relay-client.js';
|
|
12
|
+
export { rawDataToText, MessageTooLargeError } from './relay/message-adapter.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAExE,OAAO,EACN,qBAAqB,EACrB,iBAAiB,EACjB,oBAAoB,EACpB,8BAA8B,GAC9B,MAAM,qBAAqB,CAAC;AAQ7B,OAAO,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EACN,sBAAsB,EACtB,oBAAoB,EACpB,0BAA0B,GAC1B,MAAM,kCAAkC,CAAC;AAO1C,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,cAAc,GACd,MAAM,sBAAsB,CAAC;AAW9B,OAAO,EACN,WAAW,EACX,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,WAAW,EACX,YAAY,EACZ,oBAAoB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EACN,mBAAmB,EACnB,aAAa,EACb,uBAAuB,GACvB,MAAM,wBAAwB,CAAC;AAahC,OAAO,EACN,gBAAgB,EAChB,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,EAChB,6BAA6B,EAC7B,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,GACrB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAEhE,OAAO,EACN,oBAAoB,EACpB,gBAAgB,EAChB,wBAAwB,GACxB,MAAM,0BAA0B,CAAC;AASlC,OAAO,EACN,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,GACZ,MAAM,yBAAyB,CAAC;AAOjC,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ParsedInbound } from './types.js';
|
|
2
|
+
export declare function parseJsonRpcMessage(raw: unknown): ParsedInbound;
|
|
3
|
+
export declare function parseJsonText(text: string): ParsedInbound;
|
|
4
|
+
export declare function isMcpNotificationMethod(method: string): boolean;
|
|
5
|
+
/** Methods that must produce a result — missing id is a Hub contract violation. */
|
|
6
|
+
export declare function isResultBearingMethod(method: string): boolean;
|
|
7
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../src/protocol/dispatch.ts"],"names":[],"mappings":"AAKA,OAAO,EAGN,KAAK,aAAa,EAClB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,GAAG,aAAa,CA4D/D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,CAUzD;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,mFAAmF;AACnF,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAG7D"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { INVALID_REQUEST, PARSE_ERROR, jsonRpcError, } from './errors.js';
|
|
2
|
+
import { hasOwnId, isJsonRpcId, } from './types.js';
|
|
3
|
+
export function parseJsonRpcMessage(raw) {
|
|
4
|
+
if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) {
|
|
5
|
+
return {
|
|
6
|
+
kind: 'invalid',
|
|
7
|
+
id: undefined,
|
|
8
|
+
error: jsonRpcError(INVALID_REQUEST, 'Invalid Request: expected JSON object'),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const msg = raw;
|
|
12
|
+
if (msg.jsonrpc !== '2.0') {
|
|
13
|
+
return {
|
|
14
|
+
kind: 'invalid',
|
|
15
|
+
id: hasOwnId(msg) && isJsonRpcId(msg.id) ? msg.id : undefined,
|
|
16
|
+
error: jsonRpcError(INVALID_REQUEST, 'Invalid Request: jsonrpc must be "2.0"'),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
// Hub/peer response frames — do not dispatch as requests.
|
|
20
|
+
if ('result' in msg || 'error' in msg) {
|
|
21
|
+
return { kind: 'response', message: msg };
|
|
22
|
+
}
|
|
23
|
+
if (typeof msg.method !== 'string' || !msg.method) {
|
|
24
|
+
return {
|
|
25
|
+
kind: 'invalid',
|
|
26
|
+
id: hasOwnId(msg) && isJsonRpcId(msg.id) ? msg.id : undefined,
|
|
27
|
+
error: jsonRpcError(INVALID_REQUEST, 'Invalid Request: method is required'),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
if (!hasOwnId(msg)) {
|
|
31
|
+
return {
|
|
32
|
+
kind: 'notification',
|
|
33
|
+
message: {
|
|
34
|
+
jsonrpc: '2.0',
|
|
35
|
+
method: msg.method,
|
|
36
|
+
...(msg.params !== undefined ? { params: msg.params } : {}),
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
if (!isJsonRpcId(msg.id)) {
|
|
41
|
+
return {
|
|
42
|
+
kind: 'invalid',
|
|
43
|
+
id: undefined,
|
|
44
|
+
error: jsonRpcError(INVALID_REQUEST, 'Invalid Request: id must be string, number, or null'),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
return {
|
|
48
|
+
kind: 'request',
|
|
49
|
+
message: {
|
|
50
|
+
jsonrpc: '2.0',
|
|
51
|
+
id: msg.id,
|
|
52
|
+
method: msg.method,
|
|
53
|
+
...(msg.params !== undefined ? { params: msg.params } : {}),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
export function parseJsonText(text) {
|
|
58
|
+
try {
|
|
59
|
+
return parseJsonRpcMessage(JSON.parse(text));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return {
|
|
63
|
+
kind: 'invalid',
|
|
64
|
+
id: undefined,
|
|
65
|
+
error: jsonRpcError(PARSE_ERROR, 'Parse error'),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
export function isMcpNotificationMethod(method) {
|
|
70
|
+
return method === 'notifications/initialized' || method.startsWith('notifications/');
|
|
71
|
+
}
|
|
72
|
+
/** Methods that must produce a result — missing id is a Hub contract violation. */
|
|
73
|
+
export function isResultBearingMethod(method) {
|
|
74
|
+
if (isMcpNotificationMethod(method))
|
|
75
|
+
return false;
|
|
76
|
+
return true;
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=dispatch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/protocol/dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { JsonRpcErrorObject, JsonRpcId, McpErrorResponse, McpResultResponse } from './types.js';
|
|
2
|
+
export declare const PARSE_ERROR = -32700;
|
|
3
|
+
export declare const INVALID_REQUEST = -32600;
|
|
4
|
+
export declare const METHOD_NOT_FOUND = -32601;
|
|
5
|
+
export declare const INVALID_PARAMS = -32602;
|
|
6
|
+
export declare const INTERNAL_ERROR = -32603;
|
|
7
|
+
export declare const SERVER_BUSY = -32000;
|
|
8
|
+
export declare function jsonRpcError(code: number, message: string, data?: unknown): JsonRpcErrorObject;
|
|
9
|
+
export declare function resultResponse(id: JsonRpcId, result: unknown): McpResultResponse;
|
|
10
|
+
export declare function errorResponse(id: JsonRpcId, error: JsonRpcErrorObject): McpErrorResponse;
|
|
11
|
+
/**
|
|
12
|
+
* Map thrown values to a client-safe JSON-RPC error.
|
|
13
|
+
* Unmapped Error.message values are never returned to clients (leak prevention).
|
|
14
|
+
*/
|
|
15
|
+
export declare function normalizeThrownError(err: unknown, mapAppError?: (error: unknown) => JsonRpcErrorObject | undefined): JsonRpcErrorObject;
|
|
16
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/protocol/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAErG,eAAO,MAAM,WAAW,SAAS,CAAC;AAClC,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,gBAAgB,SAAS,CAAC;AACvC,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,cAAc,SAAS,CAAC;AACrC,eAAO,MAAM,WAAW,SAAS,CAAC;AAWlC,wBAAgB,YAAY,CAC3B,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE,OAAO,GACZ,kBAAkB,CAEpB;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,GAAG,iBAAiB,CAEhF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,kBAAkB,GAAG,gBAAgB,CAExF;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CACnC,GAAG,EAAE,OAAO,EACZ,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,kBAAkB,GAAG,SAAS,GAC9D,kBAAkB,CAiDpB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export const PARSE_ERROR = -32700;
|
|
2
|
+
export const INVALID_REQUEST = -32600;
|
|
3
|
+
export const METHOD_NOT_FOUND = -32601;
|
|
4
|
+
export const INVALID_PARAMS = -32602;
|
|
5
|
+
export const INTERNAL_ERROR = -32603;
|
|
6
|
+
export const SERVER_BUSY = -32000;
|
|
7
|
+
const SAFE_PROTOCOL_CODES = new Set([
|
|
8
|
+
PARSE_ERROR,
|
|
9
|
+
INVALID_REQUEST,
|
|
10
|
+
METHOD_NOT_FOUND,
|
|
11
|
+
INVALID_PARAMS,
|
|
12
|
+
INTERNAL_ERROR,
|
|
13
|
+
SERVER_BUSY,
|
|
14
|
+
]);
|
|
15
|
+
export function jsonRpcError(code, message, data) {
|
|
16
|
+
return data === undefined ? { code, message } : { code, message, data };
|
|
17
|
+
}
|
|
18
|
+
export function resultResponse(id, result) {
|
|
19
|
+
return { jsonrpc: '2.0', id, result };
|
|
20
|
+
}
|
|
21
|
+
export function errorResponse(id, error) {
|
|
22
|
+
return { jsonrpc: '2.0', id, error };
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Map thrown values to a client-safe JSON-RPC error.
|
|
26
|
+
* Unmapped Error.message values are never returned to clients (leak prevention).
|
|
27
|
+
*/
|
|
28
|
+
export function normalizeThrownError(err, mapAppError) {
|
|
29
|
+
const mapped = mapAppError?.(err);
|
|
30
|
+
if (mapped) {
|
|
31
|
+
return jsonRpcError(mapped.code, mapped.message, mapped.data);
|
|
32
|
+
}
|
|
33
|
+
if (err && typeof err === 'object') {
|
|
34
|
+
const anyErr = err;
|
|
35
|
+
const dataCode = anyErr.data && typeof anyErr.data === 'object' && anyErr.data !== null
|
|
36
|
+
? anyErr.data.code
|
|
37
|
+
: undefined;
|
|
38
|
+
if (dataCode === 'REQUEST_TIMEOUT') {
|
|
39
|
+
return jsonRpcError(INTERNAL_ERROR, 'Request timed out', { code: 'REQUEST_TIMEOUT' });
|
|
40
|
+
}
|
|
41
|
+
if (dataCode === 'RESPONSE_TOO_LARGE') {
|
|
42
|
+
return jsonRpcError(INTERNAL_ERROR, 'Response too large', { code: 'RESPONSE_TOO_LARGE' });
|
|
43
|
+
}
|
|
44
|
+
if (dataCode === 'DUPLICATE_IN_FLIGHT_ID') {
|
|
45
|
+
return jsonRpcError(INVALID_REQUEST, 'Duplicate in-flight JSON-RPC id', {
|
|
46
|
+
code: 'DUPLICATE_IN_FLIGHT_ID',
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (typeof anyErr.code === 'number' && SAFE_PROTOCOL_CODES.has(anyErr.code)) {
|
|
50
|
+
const message = typeof anyErr.message === 'string' && anyErr.message && anyErr.code !== INTERNAL_ERROR
|
|
51
|
+
? anyErr.message
|
|
52
|
+
: anyErr.code === METHOD_NOT_FOUND
|
|
53
|
+
? 'Method not found'
|
|
54
|
+
: anyErr.code === INVALID_PARAMS
|
|
55
|
+
? 'Invalid params'
|
|
56
|
+
: anyErr.code === INVALID_REQUEST
|
|
57
|
+
? 'Invalid Request'
|
|
58
|
+
: anyErr.code === PARSE_ERROR
|
|
59
|
+
? 'Parse error'
|
|
60
|
+
: anyErr.code === SERVER_BUSY
|
|
61
|
+
? 'Server busy'
|
|
62
|
+
: 'Internal error';
|
|
63
|
+
return jsonRpcError(anyErr.code, anyErr.code === INTERNAL_ERROR ? 'Internal error' : message, sanitizeErrorData(anyErr.data));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return jsonRpcError(INTERNAL_ERROR, 'Internal error');
|
|
67
|
+
}
|
|
68
|
+
function sanitizeErrorData(data) {
|
|
69
|
+
if (data === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
if (data === null)
|
|
72
|
+
return null;
|
|
73
|
+
if (typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean') {
|
|
74
|
+
return data;
|
|
75
|
+
}
|
|
76
|
+
if (typeof data === 'object' && !Array.isArray(data)) {
|
|
77
|
+
const code = data.code;
|
|
78
|
+
if (typeof code === 'string' || typeof code === 'number') {
|
|
79
|
+
return { code };
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/protocol/errors.ts"],"names":[],"mappings":"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"}
|