mirror of
https://github.com/supermemoryai/supermemory.git
synced 2026-08-25 08:22:20 +00:00
End-to-end tests that drive the deployed Supermemory MCP over streamable HTTP (no mocks): - discovery: handshake + tool/resource/prompt listing - identity: whoAmI, listProjects - memory: save -> recall round-trip, profile variants, forget, container scoping - graph/resources/prompts: memory-graph, fetch-graph-data, profile/projects, context - oauth: protected-resource discovery chain, dynamic client registration, token-endpoint negatives, and a real refresh -> access token round-trip - auth: GET / info, 401 on missing/invalid token - root-scope: x-sm-project scoping behavior Tests skip without SUPERMEMORY_API_KEY (OAuth tier-D skips without its token env vars) so CI is safe without secrets. Adds vitest + a test:e2e script and documents running + the OAuth flow in apps/mcp/README.md.
59 lines
1.9 KiB
TypeScript
59 lines
1.9 KiB
TypeScript
import { afterAll, beforeAll, describe, expect, it } from "vitest"
|
|
import { API_KEY, callTool, connect, type Session, textOf } from "./helpers"
|
|
|
|
describe.skipIf(!API_KEY)("MCP — graph, resources & prompts", () => {
|
|
let s: Session
|
|
|
|
beforeAll(async () => {
|
|
s = await connect()
|
|
})
|
|
afterAll(async () => {
|
|
await s?.close()
|
|
})
|
|
|
|
it("memory-graph returns a summary + structured documents", async () => {
|
|
const res = await callTool(s.client, "memory-graph")
|
|
expect(res.isError).toBeFalsy()
|
|
expect(textOf(res)).toMatch(/Memory Graph: \d+ documents/)
|
|
const sc = res.structuredContent as {
|
|
documents?: unknown[]
|
|
totalCount?: number
|
|
}
|
|
expect(Array.isArray(sc?.documents)).toBe(true)
|
|
})
|
|
|
|
it("fetch-graph-data returns paginated documents", async () => {
|
|
const res = await callTool(s.client, "fetch-graph-data", {
|
|
page: 1,
|
|
limit: 5,
|
|
})
|
|
expect(res.isError).toBeFalsy()
|
|
const sc = res.structuredContent as {
|
|
documents?: unknown[]
|
|
pagination?: { limit?: number }
|
|
}
|
|
expect(Array.isArray(sc?.documents)).toBe(true)
|
|
expect(sc?.pagination?.limit).toBe(5)
|
|
})
|
|
|
|
it("reads the profile resource", async () => {
|
|
const res = await s.client.readResource({ uri: "supermemory://profile" })
|
|
expect(res.contents.length).toBeGreaterThan(0)
|
|
expect(res.contents[0].mimeType).toBe("text/plain")
|
|
expect(typeof res.contents[0].text).toBe("string")
|
|
})
|
|
|
|
it("reads the projects resource as JSON", async () => {
|
|
const res = await s.client.readResource({ uri: "supermemory://projects" })
|
|
const text = res.contents[0].text as string
|
|
const parsed = JSON.parse(text)
|
|
expect(Array.isArray(parsed.projects)).toBe(true)
|
|
})
|
|
|
|
it("gets the context prompt as a system message", async () => {
|
|
const res = await s.client.getPrompt({ name: "context", arguments: {} })
|
|
expect(res.messages.length).toBeGreaterThan(0)
|
|
const text = res.messages[0].content.text as string
|
|
expect(text).toMatch(/memory|context/i)
|
|
})
|
|
})
|