@gemus/mcp-proxy 0.1.9 → 0.1.10

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.
@@ -1,68 +0,0 @@
1
- import { describe, it, expect } from 'vitest'
2
- import { Client } from '@modelcontextprotocol/sdk/client/index.js'
3
- import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js'
4
-
5
- /**
6
- * Opt-in integration test against a REAL running gemus `/api/mcp` route (#1751). Validates the Mode-B
7
- * **key-only** contract the proxy + core delivery rely on: Bearer `mak_` auth with **no**
8
- * `X-Gemus-Session-Id` header, and addressing by an explicit real `workflowId`.
9
- *
10
- * Excluded from the default runner (`*.integration.test.ts`) and gated on env so it never runs in CI or
11
- * by accident. To run against local dev:
12
- * GEMUS_IT_KEY=mak_... GEMUS_IT_WORKFLOW=<realWorkflowId> \
13
- * pnpm exec vitest run packages/gemus-mcp-proxy/src/__tests__/route.integration.test.ts
14
- * (GEMUS_IT_URL defaults to http://localhost:3000/api/mcp.) All calls here are read-only (no mutation).
15
- *
16
- * connect-per-call invariant: every case opens + closes its own client (fresh connectionNonce, #1744).
17
- */
18
- const KEY = process.env.GEMUS_IT_KEY
19
- const URL_ = process.env.GEMUS_IT_URL || 'http://localhost:3000/api/mcp'
20
- const WORKFLOW = process.env.GEMUS_IT_WORKFLOW
21
-
22
- /** Key-only client: Bearer only, deliberately NO X-Gemus-Session-Id (the Mode-B contract). */
23
- async function connectKeyOnly() {
24
- const client = new Client({ name: 'gemus-proxy-it', version: '0.1.0' })
25
- const transport = new StreamableHTTPClientTransport(new URL(URL_), {
26
- requestInit: { headers: { Authorization: `Bearer ${KEY}` } },
27
- })
28
- await client.connect(transport)
29
- return client
30
- }
31
-
32
- describe.skipIf(!KEY)('key-only /api/mcp route (real, opt-in)', () => {
33
- it('relays the full tool surface incl. execute/batch_execute (no session header)', async () => {
34
- const client = await connectKeyOnly()
35
- try {
36
- const { tools } = await client.listTools()
37
- const names = tools.map((t) => t.name)
38
- expect(names).toEqual(expect.arrayContaining(['execute', 'batch_execute', 'canvas_read', 'canvas_edit']))
39
- } finally {
40
- await client.close()
41
- }
42
- })
43
-
44
- it('serves resources (skills / knowledge) through the key-only connection', async () => {
45
- const client = await connectKeyOnly()
46
- try {
47
- const { resources } = await client.listResources()
48
- // The route exposes skill:// / knowledge:// resources; a tool-only passthrough would drop these.
49
- expect(Array.isArray(resources)).toBe(true)
50
- } finally {
51
- await client.close()
52
- }
53
- })
54
-
55
- it.skipIf(!WORKFLOW)('addresses a real workflow by explicit workflowId (key-only, no activeContext)', async () => {
56
- const client = await connectKeyOnly()
57
- try {
58
- // canvas_read is read-only; success proves key-only addressing by explicit workflowId works
59
- // without a session header (what deliverImageToNode relies on in Mode B).
60
- const res = (await client.callTool({ name: 'canvas_read', arguments: { workflowId: WORKFLOW } })) as {
61
- isError?: boolean
62
- }
63
- expect(res.isError).not.toBe(true)
64
- } finally {
65
- await client.close()
66
- }
67
- })
68
- })