catence 0.2.1-beta.24 → 0.2.1-beta.25
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.
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Keep these values synchronized with release/manifest.json; release checks
|
|
4
4
|
* deliberately reject drift before a package can be published.
|
|
5
5
|
*/
|
|
6
|
-
export declare const CATENCE_RUNTIME_VERSION = "0.2.1-beta.
|
|
6
|
+
export declare const CATENCE_RUNTIME_VERSION = "0.2.1-beta.25";
|
|
7
7
|
export declare const CATENCE_PROTOCOL_VERSION = 1;
|
|
8
8
|
export type CatenceRuntimeCapabilities = {
|
|
9
9
|
mcp: true;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Keep these values synchronized with release/manifest.json; release checks
|
|
4
4
|
* deliberately reject drift before a package can be published.
|
|
5
5
|
*/
|
|
6
|
-
export const CATENCE_RUNTIME_VERSION = '0.2.1-beta.
|
|
6
|
+
export const CATENCE_RUNTIME_VERSION = '0.2.1-beta.25';
|
|
7
7
|
export const CATENCE_PROTOCOL_VERSION = 1;
|
|
8
8
|
export function catenceRuntimeHealth() {
|
|
9
9
|
return {
|
|
@@ -109,6 +109,11 @@ export async function createOAuthApp(options) {
|
|
|
109
109
|
app.get('/.well-known/oauth-authorization-server', serveMetadata(oauthMetadata));
|
|
110
110
|
app.get('/.well-known/oauth-protected-resource', serveMetadata(protectedResourceMetadata));
|
|
111
111
|
app.get('/.well-known/oauth-protected-resource/mcp', serveMetadata(protectedResourceMetadata));
|
|
112
|
+
// The connector platform probes OIDC-style discovery on every validation
|
|
113
|
+
// pass (observed hitting the auth gate as a 401 right after fetching the
|
|
114
|
+
// RFC 8414 document); answer it publicly with the same metadata.
|
|
115
|
+
app.get('/.well-known/openid-configuration', serveMetadata(oauthMetadata));
|
|
116
|
+
app.get('/.well-known/openid-configuration/mcp', serveMetadata(oauthMetadata));
|
|
112
117
|
// DCR runs through the library's router, whose own express.json() would
|
|
113
118
|
// re-parse (and reject) an already-consumed stream; parsing here first
|
|
114
119
|
// leaves the sanitized body in place for it.
|
|
@@ -33,6 +33,9 @@ function logRequestCompletion(request, response, pathname) {
|
|
|
33
33
|
if (process.env.CATENCE_HTTP_ACCESS_LOG === '0')
|
|
34
34
|
return;
|
|
35
35
|
const startedAt = Date.now();
|
|
36
|
+
// Captured before the compatibility bridge rewrites the header so the log
|
|
37
|
+
// always shows the value the client actually sent.
|
|
38
|
+
const rawProtocolVersion = request.headers['mcp-protocol-version'];
|
|
36
39
|
response.once('finish', () => {
|
|
37
40
|
const status = response.statusCode;
|
|
38
41
|
const interesting = pathname === '/mcp' ||
|
|
@@ -46,7 +49,7 @@ function logRequestCompletion(request, response, pathname) {
|
|
|
46
49
|
const userAgent = request.headers['user-agent'];
|
|
47
50
|
if (typeof userAgent === 'string' && userAgent)
|
|
48
51
|
parts.push(`ua="${userAgent.slice(0, 120)}"`);
|
|
49
|
-
const protocolVersion =
|
|
52
|
+
const protocolVersion = rawProtocolVersion;
|
|
50
53
|
if (typeof protocolVersion === 'string' && protocolVersion)
|
|
51
54
|
parts.push(`mcp-protocol-version=${protocolVersion}`);
|
|
52
55
|
const mcpMethod = request.headers['mcp-method'];
|
|
@@ -526,7 +529,11 @@ async function handleUnauthenticatedDiscovery(request, response, paths) {
|
|
|
526
529
|
* The bundled SDK emits the legacy shape, so responses negotiated under a
|
|
527
530
|
* dated 2026 revision are rewritten on the way out. List results vary with the
|
|
528
531
|
* caller's scope, so cacheable responses from this server are always
|
|
529
|
-
* `private`.
|
|
532
|
+
* `private`. Every result also repeats the server identity in `_meta`, and
|
|
533
|
+
* tool definitions drop the SDK's `execution` field — neither the per-result
|
|
534
|
+
* `_meta.serverInfo` nor `execution` appeared in the revision's schemas for
|
|
535
|
+
* earlier SDKs, but the revision asks for the former and omits the latter.
|
|
536
|
+
* Errors and notifications carry no result and pass through.
|
|
530
537
|
*/
|
|
531
538
|
const MODERN_CACHEABLE_METHODS = new Set(['server/discover', 'tools/list', 'prompts/list', 'resources/list', 'resources/templates/list', 'resources/read']);
|
|
532
539
|
const MODERN_RESULT_TTL_MS = 300_000;
|
|
@@ -551,6 +558,25 @@ function frameModernRpcPayload(payload, method) {
|
|
|
551
558
|
framed.resultType = 'complete';
|
|
552
559
|
changed = true;
|
|
553
560
|
}
|
|
561
|
+
if (!('_meta' in framed)) {
|
|
562
|
+
framed._meta = { 'io.modelcontextprotocol/serverInfo': CATENCE_MCP_SERVER_INFO };
|
|
563
|
+
changed = true;
|
|
564
|
+
}
|
|
565
|
+
if (method === 'tools/list' && Array.isArray(framed.tools)) {
|
|
566
|
+
let stripped = false;
|
|
567
|
+
const tools = framed.tools.map((tool) => {
|
|
568
|
+
if (typeof tool !== 'object' || tool === null || Array.isArray(tool) || !('execution' in tool))
|
|
569
|
+
return tool;
|
|
570
|
+
const copy = { ...tool };
|
|
571
|
+
delete copy.execution;
|
|
572
|
+
stripped = true;
|
|
573
|
+
return copy;
|
|
574
|
+
});
|
|
575
|
+
if (stripped) {
|
|
576
|
+
framed.tools = tools;
|
|
577
|
+
changed = true;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
554
580
|
if (method !== undefined && MODERN_CACHEABLE_METHODS.has(method)) {
|
|
555
581
|
if (!('ttlMs' in framed)) {
|
|
556
582
|
framed.ttlMs = MODERN_RESULT_TTL_MS;
|
|
@@ -810,7 +836,7 @@ export function createCatenceHttpServer(options = {}) {
|
|
|
810
836
|
// The OAuth endpoints are the auth surface itself: they bypass the gate
|
|
811
837
|
// and CORS entirely and are delegated to the Express sub-app. When OAuth
|
|
812
838
|
// is effectively disabled they answer 404 — no metadata is advertised.
|
|
813
|
-
if (pathname.startsWith('/.well-known/oauth-') || pathname.startsWith('/oauth/')) {
|
|
839
|
+
if (pathname.startsWith('/.well-known/oauth-') || pathname.startsWith('/.well-known/openid-configuration') || pathname.startsWith('/oauth/')) {
|
|
814
840
|
const config = effectiveOauth();
|
|
815
841
|
if (config.enabled && config.publicUrl !== undefined) {
|
|
816
842
|
const handle = await getOauthApp(config.publicUrl);
|
package/package.json
CHANGED