Run the Verification Project Without API Keys
The rest of the book rests on one runnable project, so it makes sense to assemble it before we dig into details. It's a strict ESM TypeScript project: it spins up a real MCP stdio process and a local A2A HTTP server, runs discovery, and returns the same decision over one release snapshot. No magic and no stubs - exactly the system we're taking apart.
It all runs with a few commands, and it's worth doing right now.
npm ci --ignore-scripts
npm run check
# Separately
npm run demo:mcp
npm run demo:a2aThe set of dependencies is pinned so behavior reproduces the same for everyone - here is the whole package.json.
{
"name": "mcp-a2a-protocols-2026-project",
"version": "1.0.0",
"private": true,
"type": "module",
"engines": {
"node": ">=24.0.0"
},
"scripts": {
"build": "tsc -p tsconfig.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"test": "node --import tsx --test tests/*.test.ts",
"demo:mcp": "node --import tsx src/mcp/client.ts",
"demo:a2a": "node --import tsx src/a2a/demo.ts",
"demo": "npm run demo:mcp && npm run demo:a2a",
"check": "npm run typecheck && npm test && npm run demo"
},
"dependencies": {
"@a2a-js/sdk": "1.0.1",
"@modelcontextprotocol/client": "2.0.0",
"@modelcontextprotocol/server": "2.0.0",
"express": "5.2.1",
"zod": "4.4.3"
},
"devDependencies": {
"@types/express": "5.0.6",
"@types/node": "26.1.2",
"tsx": "4.23.1",
"typescript": "7.0.2"
}
}The files are laid out along the boundaries we've already discussed: the domain separately, the MCP layer separately, the A2A layer separately, tests alongside.
src/
domain/release-knowledge.ts
mcp/server.ts
mcp/client.ts
a2a/release-agent.ts
a2a/server.ts
a2a/demo.ts
tests/
domain.test.ts
mcp.integration.test.ts
a2a.integration.test.ts
package-lock.jsonThree deliberate decisions sit behind this layout. First: 14 contract tests check the domain, discovery, schema metadata, MCP calls, the Agent Card, and both Task outcomes - input-required and completed. Second: two E2E exercise real transports - a child MCP stdio process and a temporary A2A HTTP port, not in-memory function calls; only this way do you test framing and connection shutdown. Third: zero keys - no model is needed, so the test proves the protocol and the code, not the random quality of an LLM.
Why there is no cloud model here. MCP and A2A are contracts between programs. An LLM can be added to the host or the AgentExecutor without changing the transport and public types. It's useful to prove the protocol plumbing separately from reasoning first: then you know exactly what breaks - the protocol or the model.
And an honest caveat about versions, without which a book on living protocols goes stale fast.
Versions are a snapshot as of 2026-08-01.@modelcontextprotocol/server2.0.0,@modelcontextprotocol/client2.0.0,@a2a-js/sdk1.0.1, TypeScript 7.0.2. Before a new production release, upgrade deliberately and re-run the contract tests.
The project runs - now let's take it apart piece by piece, starting with how the MCP side is built.