Test Layers
The MCP server has three test layers, each exercising a different boundary:| Layer | What it tests | Transport | Giza SDK |
|---|---|---|---|
| Unit | Individual tool handlers, formatters, config resolution | None (direct function calls) | Mocked |
| Integration | MCP protocol: tool registration, Zod schema wiring, session state, error propagation | InMemoryTransport (in-process) | Mocked |
| E2E | Full process: CLI startup, stdio/HTTP transport, real MCP handshake | StdioClientTransport / StreamableHTTPClientTransport (out-of-process) | Real SDK (env-configured) |
Running Tests
From thepackages/mcp-server/ directory:
bun test from the package directory. E2E tests automatically skip when dist/cli.js is missing (no build) or when running from a different working directory.
Integration Tests
Integration tests wire an MCPClient to a real GizaServer via InMemoryTransport, with the Giza SDK mocked. This exercises the full MCP protocol layer without spawning processes.
Structure
Test Harness
UsecreateTestHarness() to get a connected client with mocked SDK:
What Integration Tests Cover
- Server lifecycle: Construction,
McpServerinstance type, tool accessibility after connection - Tool discovery: Correct tool count, schema structure, name uniqueness, exact tool name set
- Tool execution:
connect_walletsuccess,get_tokenswithout wallet,get_portfoliowith/without wallet,optimizeparameter forwarding - Wallet session: Connect-then-operate flow, disconnect clears state, second connect overwrites, state persists across calls
- Error propagation: All error types (
WalletNotConnectedError,GizaAPIError,TimeoutError,NetworkError,GizaError, genericError, non-Error throws) map toisError: truewith correct messages - Prompt registration:
listPromptsreturns system prompt,getPromptreturns default text, custom prompt override works - Cherry-picked tools: Subset registration (2 tools, 6 tools), calling unregistered tool returns error
E2E Tests
E2E tests spawn the built CLI as a child process and connect to it using real MCP client transports.Structure
Prerequisites
E2E tests require a build:test:e2e script handles this automatically. When running via bun test, E2E suites skip if dist/cli.js doesn’t exist.
Environment
E2E tests inject test environment variables into the spawned process:| Variable | Test Value |
|---|---|
GIZA_API_KEY | test-key |
GIZA_PARTNER_NAME | test |
GIZA_API_URL | https://api.test.giza.tech |
CHAIN_ID | 8453 |
What E2E Tests Cover
- Stdio transport: Client connection,
listToolsreturns all tools,listPrompts, wallet connect with valid/invalid addresses - HTTP transport:
/healthreturns{ status: "ok" }, unknown routes return 404, MCP client connects and lists tools,connect_walletthrough HTTP - Wallet errors:
get_portfolioandactivate_agentwithout wallet return errors (not crashes),disconnect_walletwithout prior connect returns “No wallet” message - Validation: Empty string and non-hex wallet addresses rejected by Zod schemas through the MCP protocol
Adding New Tests
Adding an integration test
- Create a new
.test.tsfile insrc/__integration__/ - Import
createTestHarnessfrom the helpers - Use
client.callTool(),client.listTools(), orclient.listPrompts()to exercise the MCP protocol - If you need to configure mock behavior, access
mockGiza.__mockAgentfor agent methods ormockGizadirectly for top-level SDK methods
Adding an E2E test
- Create a new
.test.tsfile insrc/__e2e__/ - Import helpers and
isE2EAvailablefrom./helpers/stdio-client.js - Use conditional describe:
const run = isE2EAvailable() ? describe : describe.skip; - Use
createStdioClient()orcreateHttpClient(port)inbeforeAll - Guard
afterAllwithif (cleanup) await cleanup()