Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion packages/adt-mcp/src/lib/tools/scope-catalogue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,11 @@ function isScopedReadResourceAllowed(
name: string,
arguments_: Record<string, unknown>,
): boolean {
if (name !== 'get_object' && name !== 'get_object_structure') return true;
// Fail closed: a scoped read must not reach tools that take unbounded
// resource identifiers (e.g. `cts_*` transport reads). The toolNames
// contract whitelist already blocks them at parse time; this keeps the
// dispatch layer equally strict if that whitelist ever widens.
if (name !== 'get_object' && name !== 'get_object_structure') return false;
if (scoped.resourceKeys.length === 0) return false;
const key = canonicalObjectKey(arguments_.objectType, arguments_.objectName);
return Boolean(key && scoped.resourceKeys.includes(key));
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/adt-execution-policy.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { describe, it } from 'vitest';
import {
isMcpInvocationDispatchPolicySupported,
parseScopedAdtInvocationPolicy,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { test } from 'vitest';
import {
isMcpToolAllowed,
isMcpToolListed,
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/delegated-assistant-policy.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { describe, it } from 'vitest';
import {
parseDelegatedAssistantReadPolicy,
type TrustedMcpInvocationClaims,
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/destination-registry.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { test } from 'vitest';
import {
createDestinationContextRegistry,
type DestinationContextFactory,
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/flow-checkout-tr.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import assert from 'node:assert/strict';
import { mkdtemp, realpath } from 'node:fs/promises';
import { tmpdir } from 'node:os';
import { join } from 'node:path';
import test from 'node:test';
import { test } from 'vitest';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import type { AdtClient } from '@abapify/adt-client';
import type { FormatPlugin } from '@abapify/adt-plugin';
Expand Down
18 changes: 9 additions & 9 deletions packages/adt-mcp/tests/http-auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* an allowed (authenticated) call, and 401 for an unauthenticated one.
* That's enough to distinguish "auth passed" from "auth blocked".
*/
import { describe, it, before, after } from 'node:test';
import { describe, it, beforeAll, afterAll } from 'vitest';
import { tlsFetch, startTestServer } from './_tls-fixtures.js';

import assert from 'node:assert';
Expand Down Expand Up @@ -82,12 +82,12 @@ async function probeMcp(

describe('adt-mcp HTTP auth — mode=none (default)', () => {
let server: RunningHttpServer;
before(async () => {
beforeAll(async () => {
server = await startTestServer({
registry: emptyRegistry(),
});
});
after(async () => {
afterAll(async () => {
await server.close();
});

Expand All @@ -109,14 +109,14 @@ describe('adt-mcp HTTP auth — mode=none (default)', () => {
describe('adt-mcp HTTP auth — mode=bearer', () => {
let server: RunningHttpServer;
const token = 'super-secret-test-token-abc123';
before(async () => {
beforeAll(async () => {
server = await startTestServer({
authMode: 'bearer',
authToken: token,
registry: emptyRegistry(),
});
});
after(async () => {
afterAll(async () => {
await server.close();
});

Expand Down Expand Up @@ -169,13 +169,13 @@ describe('adt-mcp HTTP auth — mode=bearer', () => {

describe('adt-mcp HTTP auth — mode=proxy (trustForwardedAuth)', () => {
let server: RunningHttpServer;
before(async () => {
beforeAll(async () => {
server = await startTestServer({
trustForwardedAuth: true,
registry: emptyRegistry(),
});
});
after(async () => {
afterAll(async () => {
await server.close();
});

Expand All @@ -196,13 +196,13 @@ describe('adt-mcp HTTP auth — mode=proxy (trustForwardedAuth)', () => {

describe('adt-mcp HTTP — CORS', () => {
let server: RunningHttpServer;
before(async () => {
beforeAll(async () => {
server = await startTestServer({
allowedOrigins: ['https://app.example.com'],
registry: emptyRegistry(),
});
});
after(async () => {
afterAll(async () => {
await server.close();
});

Expand Down
6 changes: 3 additions & 3 deletions packages/adt-mcp/tests/http-changeset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* - rollback path releases the lock on the mock server
*/

import { describe, it, before, after } from 'node:test';
import { describe, it, beforeAll, afterAll } from 'vitest';
import { createTlsTransport, startTestServer } from './_tls-fixtures.js';

import assert from 'node:assert';
Expand Down Expand Up @@ -53,7 +53,7 @@ function parseToolText(result: unknown): { json: unknown; isError: boolean } {
}

describe('adt-mcp HTTP — Wave 3 changesets', () => {
before(async () => {
beforeAll(async () => {
mockAdt = createMockAdtServer();
const info = await mockAdt.start();
mockPort = info.port;
Expand All @@ -65,7 +65,7 @@ describe('adt-mcp HTTP — Wave 3 changesets', () => {
});
});

after(async () => {
afterAll(async () => {
await http?.close();
await mockAdt?.stop();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/http-destination-scope.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import test from 'node:test';
import { test } from 'vitest';
import {
tlsFetch,
createTlsTransport,
Expand Down
4 changes: 2 additions & 2 deletions packages/adt-mcp/tests/http-handler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Verifies that the HTTP MCP transport can be composed under a listener that
* is owned by the embedding application.
*/
import { after, describe, it } from 'node:test';
import { afterAll, describe, it } from 'vitest';
import assert from 'node:assert';
import http from 'node:http';
import { createHttpMcpHandler } from '../src/lib/http/server.js';
Expand All @@ -11,7 +11,7 @@ import { createSessionRegistry } from '../src/lib/session/registry.js';
describe('createHttpMcpHandler', () => {
const listeners: http.Server[] = [];

after(async () => {
afterAll(async () => {
await Promise.all(
listeners.map(async (listener) => {
if (!listener.listening) return;
Expand Down
6 changes: 3 additions & 3 deletions packages/adt-mcp/tests/http-integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* sap_disconnect lifecycle end-to-end.
*/

import { describe, it, before, after } from 'node:test';
import { describe, it, beforeAll, afterAll } from 'vitest';
import { createTlsTransport, startTestServer } from './_tls-fixtures.js';

import assert from 'node:assert';
Expand Down Expand Up @@ -41,7 +41,7 @@ function buildMockParams(): ConnectionParams {
}

describe('adt-mcp HTTP integration', () => {
before(async () => {
beforeAll(async () => {
mockAdt = createMockAdtServer();
const info = await mockAdt.start();
mockPort = info.port;
Expand All @@ -60,7 +60,7 @@ describe('adt-mcp HTTP integration', () => {
});
});

after(async () => {
afterAll(async () => {
await http?.close();
await mockAdt?.stop();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/http-invocation-auth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* and scope, and that a session cannot be continued with another JTI.
*/
import assert from 'node:assert/strict';
import test from 'node:test';
import { test } from 'vitest';
import {
tlsFetch,
createTlsTransport,
Expand Down
11 changes: 7 additions & 4 deletions packages/adt-mcp/tests/http-invocation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* real ES256 JWS values — the verifier never trusts decoded, unsigned data.
*/
import assert from 'node:assert/strict';
import { before, describe, it } from 'node:test';
import { beforeAll, describe, it } from 'vitest';
import {
generateKeyPair,
SignJWT,
Expand All @@ -25,7 +25,7 @@ let privateKey: CryptoKey;
let publicKey: CryptoKey;
let verifier: ReturnType<typeof createMcpInvocationVerifier>;

before(async () => {
beforeAll(async () => {
({ privateKey, publicKey } = await generateKeyPair('ES256'));
verifier = createMcpInvocationVerifier({
publicKey,
Expand Down Expand Up @@ -106,8 +106,11 @@ describe('MCP invocation verifier', () => {
classes: ['server', 'read'],
destinationKeys: ['trl-rise'],
correlationId: 'correlation-001',
constraint: { systemSid: 'TRL', frozenScope: ['ZCL_ADT_REVIEW'] },
limits: { maxSourceBytes: 65_536 },
constraint: Object.assign(Object.create(null), {
systemSid: 'TRL',
frozenScope: ['ZCL_ADT_REVIEW'],
}),
limits: Object.assign(Object.create(null), { maxSourceBytes: 65_536 }),
});
assert.ok(verified);
assert.ok(Object.isFrozen(verified));
Expand Down
10 changes: 5 additions & 5 deletions packages/adt-mcp/tests/http-oauth.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* the `onOAuthUserHint` internal hook to verify the claim-extraction
* logic end-to-end.
*/
import { describe, it, before, after } from 'node:test';
import { describe, it, beforeAll, afterAll } from 'vitest';
import { tlsFetch, startTestServer } from './_tls-fixtures.js';

import assert from 'node:assert';
Expand Down Expand Up @@ -154,7 +154,7 @@ describe('adt-mcp HTTP auth — mode=oauth (JWKS explicit)', () => {
let server: RunningHttpServer;
const capturedHints: (UserHint | undefined)[] = [];

before(async () => {
beforeAll(async () => {
__resetOAuthDiscoveryCacheForTests();
idp = await startMockIdp();
server = await startTestServer({
Expand All @@ -170,7 +170,7 @@ describe('adt-mcp HTTP auth — mode=oauth (JWKS explicit)', () => {
registry: emptyRegistry(),
});
});
after(async () => {
afterAll(async () => {
await server.close();
await idp.close();
});
Expand Down Expand Up @@ -274,7 +274,7 @@ describe('adt-mcp HTTP auth — mode=oauth (OIDC discovery fallback)', () => {
let idp: MockIdp;
let server: RunningHttpServer;

before(async () => {
beforeAll(async () => {
__resetOAuthDiscoveryCacheForTests();
idp = await startMockIdp();
// No jwksUri → force discovery.
Expand All @@ -287,7 +287,7 @@ describe('adt-mcp HTTP auth — mode=oauth (OIDC discovery fallback)', () => {
registry: emptyRegistry(),
});
});
after(async () => {
afterAll(async () => {
await server.close();
await idp.close();
});
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/integration.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* Integration tests for the adt-mcp package.
*
* Uses node:test (native Node.js test runner) and the MCP SDK's
* Uses vitest and the MCP SDK's
* InMemoryTransport so we can exercise every tool without stdio.
*
* A lightweight mock ADT HTTP server provides fixture responses.
Expand Down
2 changes: 1 addition & 1 deletion packages/adt-mcp/tests/safe-execute-enforcement.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import assert from 'node:assert/strict';
import { describe, it } from 'node:test';
import { describe, it } from 'vitest';
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { destinationModeServer } from '../src/lib/tools/destination-mode.js';
import { registerAtcRunTool } from '../src/lib/tools/atc-run.js';
Expand Down
Loading
Loading