{"_id":"@402md/a2a","_rev":"2-26672466bcfff38db495ccb5008dc7e1","name":"@402md/a2a","dist-tags":{"latest":"0.1.1"},"versions":{"0.1.0":{"name":"@402md/a2a","version":"0.1.0","license":"MIT","_id":"@402md/a2a@0.1.0","maintainers":[{"name":"henriquebreim","email":"developers@402.md"}],"dist":{"shasum":"ee1f504dcc9927a39a1d0b9c43e81c4edef55d6b","tarball":"https://registry.npmjs.org/@402md/a2a/-/a2a-0.1.0.tgz","fileCount":8,"integrity":"sha512-RmXpc8BDSXaHx85Jag1h5fEjI7GXC6+3mi4MdwLLCrbn8qqscO1QLvCQftu3vHm8j9wWenNpIlfBH6u0BtEjXg==","signatures":[{"sig":"MEYCIQDvs1uq7lPD4ECKBqaF212ecUNb1ZGkwmg3Ygx1BvdoxwIhAIMrWHeIJnE9uOS02Q4wgJvY+eTEUkpx50d9cEtqzt5Z","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":161547},"main":"./dist/index.cjs","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"gitHead":"0076005656275207953ad383e49aedbda57e4d29","scripts":{"dev":"tsup --watch","build":"tsup"},"_npmUser":{"name":"henriquebreim","email":"developers@402.md"},"_npmVersion":"11.2.0","description":"A2A protocol SDK for Node.js — discover, publish, and communicate with AI agents using the Agent-to-Agent standard","directories":{},"_nodeVersion":"22.13.1","dependencies":{"@402md/skillmd":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"tsup":"^8.5.0","typescript":"^5.8.3"},"_npmOperationalInternal":{"tmp":"tmp/a2a_0.1.0_1773519046085_0.08130661332984879","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@402md/a2a","version":"0.1.1","description":"A2A protocol SDK for Node.js — discover, publish, and communicate with AI agents using the Agent-to-Agent standard","type":"module","main":"./dist/index.cjs","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"require":{"types":"./dist/index.d.cts","default":"./dist/index.cjs"}}},"scripts":{"build":"tsup","dev":"tsup --watch","lint":"eslint src/","lint:fix":"eslint src/ --fix","format":"prettier --write 'src/**/*.ts' '__tests__/**/*.ts'","format:check":"prettier --check 'src/**/*.ts' '__tests__/**/*.ts'","test":"vitest run","test:watch":"vitest"},"dependencies":{"@402md/skillmd":"^0.1.3"},"devDependencies":{"@eslint/js":"^10.0.1","eslint":"^10.0.3","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5","globals":"^17.4.0","prettier":"^3.8.1","tsup":"^8.5.0","typescript":"^5.8.3","typescript-eslint":"^8.57.0","vitest":"^4.1.0"},"license":"MIT","engines":{"node":">=18"},"_id":"@402md/a2a@0.1.1","gitHead":"c43e74ffb2d2a421bb7f9907ab4e4c20501d5120","_nodeVersion":"22.13.1","_npmVersion":"11.2.0","dist":{"integrity":"sha512-aBq/3NiSyNMqgpNz9JzrocoorDKVAPLbFNX6quXjzxZitxzaJUPdrEQaCA+ZzV/KgiE5gB+Y/vQefQlLQ+m7Dw==","shasum":"568fc99b82270b66758d029074ef82aee4c31242","tarball":"https://registry.npmjs.org/@402md/a2a/-/a2a-0.1.1.tgz","fileCount":8,"unpackedSize":169484,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFa45bxNyvIpW7Tu6obxTNUqH9EymEOCPWJRhtGfw/5gAiEA4pWptDTHnljAos+RfoisrIKjFCuSaeyEQSNjUjNFvVk="}]},"_npmUser":{"name":"henriquebreim","email":"developers@402.md"},"directories":{},"maintainers":[{"name":"henriquebreim","email":"developers@402.md"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/a2a_0.1.1_1773539305735_0.6143451106063715"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-14T20:10:45.941Z","modified":"2026-03-15T01:48:26.040Z","0.1.0":"2026-03-14T20:10:46.240Z","0.1.1":"2026-03-15T01:48:25.894Z"},"license":"MIT","description":"A2A protocol SDK for Node.js — discover, publish, and communicate with AI agents using the Agent-to-Agent standard","maintainers":[{"name":"henriquebreim","email":"developers@402.md"}],"readme":"# @402md/a2a\n\n[![npm version](https://img.shields.io/npm/v/@402md/a2a)](https://www.npmjs.com/package/@402md/a2a)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)\n[![A2A](https://img.shields.io/badge/A2A-v0.3.0-00C853)](https://google.github.io/A2A/)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178C6)](https://www.typescriptlang.org)\n[![x402](https://img.shields.io/badge/x402-compatible-green)](https://x402.org)\n[![JSON--RPC](https://img.shields.io/badge/JSON--RPC-2.0-orange)](https://www.jsonrpc.org/specification)\n\nA2A protocol SDK for Node.js. Discover, publish, and communicate with AI agents using the [Agent-to-Agent (A2A)](https://google.github.io/A2A/) standard v0.3.0.\n\n- **Serve** — Middleware to serve your Agent Card at `/.well-known/agent-card.json`\n- **Client** — JSON-RPC client to send tasks to remote agents (with SSE streaming)\n- **Handler** — JSON-RPC server middleware to receive and process tasks\n- **Validate** — Validate Agent Cards against the spec\n- **Discover** — Fetch Agent Cards from any A2A-compatible agent\n\nZero framework lock-in. Works with Express, Hono, Next.js, Connect, and raw Node.js HTTP.\n\n## Installation\n\n```bash\nnpm install @402md/a2a\n```\n\n---\n\n## Quick Start\n\n### 1. Publish your agent (serve the Agent Card)\n\n```typescript\nimport express from 'express'\nimport { serveAgentCard } from '@402md/a2a'\n\nconst app = express()\n\n// Reads ./SKILL.md and serves the Agent Card automatically\napp.use(serveAgentCard())\n\napp.listen(3000)\n```\n\n```bash\ncurl http://localhost:3000/.well-known/agent-card.json\n```\n\n### Next.js App Router\n\n```typescript\n// app/.well-known/agent-card.json/route.ts\nimport { agentCardResponse } from '@402md/a2a'\n\nexport const GET = agentCardResponse()\n```\n\n```typescript\n// app/a2a/route.ts\nimport { handleA2ANext } from '@402md/a2a'\n\nexport const POST = handleA2ANext({\n  onSendTask: async (params) => ({\n    id: params.id,\n    status: {\n      state: 'completed',\n      message: {\n        role: 'agent',\n        parts: [{ type: 'text', text: `You said: ${params.message.parts[0].type === 'text' ? params.message.parts[0].text : ''}` }]\n      }\n    }\n  })\n})\n```\n\n### 2. Discover a remote agent\n\n```typescript\nimport { fetchAgentCard } from '@402md/a2a'\n\nconst card = await fetchAgentCard('https://agent.example.com')\nconsole.log(card.name, card.skills)\n```\n\n### 3. Send a task to a remote agent\n\n```typescript\nimport { A2AClient } from '@402md/a2a'\n\nconst client = new A2AClient('https://agent.example.com')\n\nconst task = await client.sendTask({\n  role: 'user',\n  parts: [{ type: 'text', text: 'What is the weather in Tokyo?' }]\n})\n\nconsole.log(task.status.state) // 'completed'\nconsole.log(task.status.message) // agent's response\n```\n\n### 4. Handle incoming tasks (be an A2A server)\n\n```typescript\nimport express from 'express'\nimport { serveAgentCard, handleA2A } from '@402md/a2a'\n\nconst app = express()\n\n// Discovery\napp.use(serveAgentCard())\n\n// Task handler\napp.use(handleA2A({\n  onSendTask: async (params) => {\n    const userText = params.message.parts\n      .filter(p => p.type === 'text')\n      .map(p => p.text)\n      .join(' ')\n\n    return {\n      id: params.id,\n      status: {\n        state: 'completed',\n        message: {\n          role: 'agent',\n          parts: [{ type: 'text', text: `You said: ${userText}` }]\n        }\n      }\n    }\n  }\n}))\n\napp.listen(3000)\n```\n\n---\n\n## API Reference\n\n### Discovery\n\n#### `serveAgentCard(options?)`\n\nExpress/Connect middleware that serves the Agent Card at `/.well-known/agent-card.json`.\n\n```typescript\nfunction serveAgentCard(options?: ServeAgentCardOptions | string): Middleware\n```\n\n- Reads `SKILL.md` once at startup, caches the JSON\n- String shorthand: `serveAgentCard('./path/to/SKILL.md')`\n- `Cache-Control: public, max-age=3600` by default\n\n#### `serveAgentCardHono(options?)`\n\nSame as `serveAgentCard`, but for Hono:\n\n```typescript\nimport { Hono } from 'hono'\nimport { serveAgentCardHono } from '@402md/a2a'\n\nconst app = new Hono()\napp.use(serveAgentCardHono())\n```\n\n#### `ServeAgentCardOptions`\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `skillMdPath` | `string` | `'./SKILL.md'` | Path to the SKILL.md file |\n| `card` | `A2AAgentCard` | — | Pre-built card (skips file reading) |\n| `maxAge` | `number` | `3600` | Cache-Control max-age in seconds |\n| `url` | `string` | manifest `base_url` | Override the agent's URL |\n| `providerName` | `string` | manifest `author` | Provider organization name |\n| `providerUrl` | `string` | — | Provider URL |\n| `authSchemes` | `A2AAuthScheme[]` | `[{ scheme: 'x402' }]` | Authentication schemes |\n| `preferredTransport` | `A2ATransport` | `'REST'` | Transport protocol |\n| `streaming` | `boolean` | — | Streaming support |\n| `pushNotifications` | `boolean` | — | Push notification support |\n| `documentationUrl` | `string` | — | Link to docs |\n\n#### `fetchAgentCard(baseUrl, options?)`\n\nFetch a remote agent's Agent Card:\n\n```typescript\nconst card = await fetchAgentCard('https://agent.example.com')\n// Hits GET https://agent.example.com/.well-known/agent-card.json\n```\n\nSupports `AbortSignal` for cancellation:\n\n```typescript\nconst controller = new AbortController()\nconst card = await fetchAgentCard(url, { signal: controller.signal })\n```\n\n#### `toAgentCard(manifest, options?)`\n\nPure function to convert a `SkillManifest` into an `A2AAgentCard`. Re-exported from `@402md/skillmd`:\n\n```typescript\nimport { toAgentCard } from '@402md/a2a'\nimport { parseSkillMd } from '@402md/skillmd'\n\nconst manifest = parseSkillMd(raw)\nconst card = toAgentCard(manifest, { providerName: 'Acme Corp' })\n```\n\n**Mapping:**\n\n| Agent Card field | Source |\n|-----------------|--------|\n| `schemaVersion` | `'1.0'` |\n| `humanReadableId` | `author/name` or `name` |\n| `agentVersion` | `manifest.version` or `'1.0.0'` |\n| `name` | `manifest.displayName` or `manifest.name` |\n| `url` | `options.url` or `manifest.base_url` |\n| `protocolVersion` | `'0.3.0'` |\n| `authSchemes` | `options.authSchemes` or `[{ scheme: 'x402' }]` |\n| `skills[]` | One per `manifest.endpoints` |\n\n---\n\n### Client\n\n#### `A2AClient`\n\nFull A2A JSON-RPC client with support for all standard methods:\n\n```typescript\nconst client = new A2AClient('https://agent.example.com', {\n  headers: { 'Authorization': 'Bearer token' }\n})\n```\n\n**Methods:**\n\n| Method | Description |\n|--------|-------------|\n| `client.agentCard()` | Fetch the agent's Agent Card |\n| `client.sendTask(params)` | Send a task (`tasks/send`) |\n| `client.sendTask(message, id?)` | Shorthand — pass a `Message` directly |\n| `client.getTask(id, historyLength?)` | Get task status (`tasks/get`) |\n| `client.cancelTask(id)` | Cancel a task (`tasks/cancel`) |\n| `client.sendTaskSubscribe(params)` | Stream task updates via SSE (`tasks/sendSubscribe`) |\n| `client.setPushNotification(id, config)` | Set push notification config |\n| `client.getPushNotification(id)` | Get push notification config |\n\n#### Sending a task\n\n```typescript\n// Full params\nconst task = await client.sendTask({\n  id: 'task-123',\n  message: {\n    role: 'user',\n    parts: [{ type: 'text', text: 'Summarize this document' }]\n  },\n  historyLength: 5\n})\n\n// Shorthand\nconst task = await client.sendTask(\n  { role: 'user', parts: [{ type: 'text', text: 'Hello' }] },\n  'task-456' // optional id, auto-generated if omitted\n)\n```\n\n#### Streaming\n\n```typescript\nconst params = {\n  id: 'task-789',\n  message: {\n    role: 'user' as const,\n    parts: [{ type: 'text' as const, text: 'Write a poem' }]\n  }\n}\n\nfor await (const event of client.sendTaskSubscribe(params)) {\n  if (event.type === 'status') {\n    console.log('Status:', event.status.state)\n  } else if (event.type === 'artifact') {\n    console.log('Artifact:', event.artifact)\n  }\n}\n```\n\n#### Error handling\n\n```typescript\nimport { A2AClientError } from '@402md/a2a'\n\ntry {\n  await client.sendTask(message)\n} catch (err) {\n  if (err instanceof A2AClientError) {\n    console.log(err.statusCode) // HTTP status (e.g. 404)\n    console.log(err.rpcCode)    // JSON-RPC error code (e.g. -32001)\n    console.log(err.data)       // Extra error data from server\n  }\n}\n```\n\n---\n\n### Server Handler\n\n#### `handleA2A(handlers, options?)`\n\nExpress/Connect middleware that handles incoming A2A JSON-RPC requests:\n\n```typescript\nfunction handleA2A(handlers: A2AHandlers, options?: HandleA2AOptions): Middleware\n```\n\n**`A2AHandlers`:**\n\n| Handler | Required | Method | Description |\n|---------|----------|--------|-------------|\n| `onSendTask` | Yes | `tasks/send` | Process an incoming task |\n| `onGetTask` | No | `tasks/get` | Return task status (returns error if not implemented) |\n| `onCancelTask` | No | `tasks/cancel` | Cancel a task (returns error if not implemented) |\n\n**`HandleA2AOptions`:**\n\n| Option | Type | Default | Description |\n|--------|------|---------|-------------|\n| `path` | `string` | `'/'` | Path to listen on for JSON-RPC requests |\n\n#### Full server example with task persistence\n\n```typescript\nimport express from 'express'\nimport { serveAgentCard, handleA2A } from '@402md/a2a'\nimport type { Task, SendTaskParams, GetTaskParams, CancelTaskParams } from '@402md/a2a'\n\nconst app = express()\nconst tasks = new Map<string, Task>()\n\napp.use(serveAgentCard())\n\napp.use(handleA2A({\n  onSendTask: async (params: SendTaskParams): Promise<Task> => {\n    const task: Task = {\n      id: params.id,\n      status: {\n        state: 'completed',\n        message: {\n          role: 'agent',\n          parts: [{ type: 'text', text: 'Task processed!' }]\n        },\n        timestamp: new Date().toISOString()\n      },\n      history: [params.message]\n    }\n\n    tasks.set(task.id, task)\n    return task\n  },\n\n  onGetTask: async (params: GetTaskParams): Promise<Task> => {\n    const task = tasks.get(params.id)\n    if (!task) throw new Error('Task not found')\n    return task\n  },\n\n  onCancelTask: async (params: CancelTaskParams): Promise<Task> => {\n    const task = tasks.get(params.id)\n    if (!task) throw new Error('Task not found')\n    task.status = { state: 'canceled', timestamp: new Date().toISOString() }\n    return task\n  }\n}))\n\napp.listen(3000)\n```\n\n---\n\n### Next.js App Router\n\n#### `agentCardResponse(options?)`\n\nNext.js route handler for serving the Agent Card. Use in `app/.well-known/agent-card.json/route.ts`:\n\n```typescript\nfunction agentCardResponse(options?: ServeAgentCardOptions | string): NextRouteHandler\n```\n\nAccepts the same `ServeAgentCardOptions` as `serveAgentCard()`. The card is built once and cached.\n\n```typescript\n// Default — reads ./SKILL.md\nexport const GET = agentCardResponse()\n\n// Custom path\nexport const GET = agentCardResponse('./skills/my-agent.md')\n\n// Pre-built card\nexport const GET = agentCardResponse({ card: myCard, maxAge: 7200 })\n```\n\n#### `handleA2ANext(handlers)`\n\nNext.js route handler for A2A JSON-RPC requests. Use in `app/a2a/route.ts` (or any route):\n\n```typescript\nfunction handleA2ANext(handlers: A2AHandlers): NextRouteHandler\n```\n\nSame `A2AHandlers` interface as `handleA2A()` — `onSendTask` (required), `onGetTask`, `onCancelTask`.\n\n#### Full Next.js example\n\n```\napp/\n  .well-known/\n    agent-card.json/\n      route.ts          ← agentCardResponse()\n  a2a/\n    route.ts            ← handleA2ANext()\n```\n\n```typescript\n// app/.well-known/agent-card.json/route.ts\nimport { agentCardResponse } from '@402md/a2a'\n\nexport const GET = agentCardResponse()\n```\n\n```typescript\n// app/a2a/route.ts\nimport { handleA2ANext } from '@402md/a2a'\nimport type { Task, SendTaskParams, GetTaskParams } from '@402md/a2a'\n\nconst tasks = new Map<string, Task>()\n\nexport const POST = handleA2ANext({\n  onSendTask: async (params: SendTaskParams): Promise<Task> => {\n    const task: Task = {\n      id: params.id,\n      status: {\n        state: 'completed',\n        message: {\n          role: 'agent',\n          parts: [{ type: 'text', text: 'Processed by Next.js!' }]\n        },\n        timestamp: new Date().toISOString()\n      },\n      history: [params.message]\n    }\n    tasks.set(task.id, task)\n    return task\n  },\n\n  onGetTask: async (params: GetTaskParams): Promise<Task> => {\n    const task = tasks.get(params.id)\n    if (!task) throw new Error('Task not found')\n    return task\n  }\n})\n```\n\n---\n\n### Validation\n\n#### `validateAgentCard(card)`\n\nValidate any object against the A2A v0.3.0 Agent Card spec:\n\n```typescript\nimport { validateAgentCard } from '@402md/a2a'\n\nconst result = validateAgentCard(someCard)\n\nif (!result.valid) {\n  console.error('Errors:', result.errors)\n}\n\nif (result.warnings.length > 0) {\n  console.warn('Warnings:', result.warnings)\n}\n```\n\n**What it checks:**\n\n| Category | Checks |\n|----------|--------|\n| **Required fields** | `schemaVersion`, `humanReadableId`, `agentVersion`, `name`, `description`, `url`, `protocolVersion`, `preferredTransport` |\n| **Provider** | Must have `provider.name` |\n| **Capabilities** | Must have `capabilities.a2aVersion` |\n| **Auth** | `authSchemes` must be a non-empty array with valid `scheme` fields |\n| **URL** | `url` and `documentationUrl` must be valid URLs |\n| **Skills** | Each skill must have `id`, `name`, `description` |\n| **Warnings** | Missing `skills`, missing `documentationUrl` |\n\n#### Validate a fetched card\n\n```typescript\nimport { fetchAgentCard, validateAgentCard } from '@402md/a2a'\n\nconst card = await fetchAgentCard('https://agent.example.com')\nconst { valid, errors, warnings } = validateAgentCard(card as Record<string, unknown>)\n\nif (!valid) {\n  console.error('This agent card is non-compliant:', errors)\n}\n```\n\n---\n\n## Combining Everything\n\n### Full A2A agent with @402md/gateway\n\n```typescript\nimport express from 'express'\nimport { Gateway } from '@402md/gateway'\nimport { serveAgentCard, handleA2A } from '@402md/a2a'\n\nconst app = express()\nconst gateway = new Gateway({ skillToken: process.env.SKILL_TOKEN })\n\n// 1. Discovery — public\napp.use(serveAgentCard())\n\n// 2. A2A protocol — handles tasks/send, tasks/get, etc.\napp.use('/a2a', handleA2A({\n  onSendTask: async (params) => {\n    // Your agent logic here\n    return {\n      id: params.id,\n      status: { state: 'completed', message: {\n        role: 'agent',\n        parts: [{ type: 'text', text: 'Done!' }]\n      }}\n    }\n  }\n}, { path: '/a2a' }))\n\n// 3. Direct REST API — protected by x402 payment\napp.post('/v1/generate', gateway.protect(), (req, res) => {\n  res.json({ result: 'paid content' })\n})\n\napp.listen(3000)\n```\n\n### Agent-to-agent communication\n\n```typescript\nimport { A2AClient, fetchAgentCard } from '@402md/a2a'\n\n// Discover\nconst card = await fetchAgentCard('https://other-agent.example.com')\nconsole.log(`Found: ${card.name} with ${card.skills?.length ?? 0} skills`)\n\n// Communicate\nconst client = new A2AClient('https://other-agent.example.com')\nconst task = await client.sendTask({\n  role: 'user',\n  parts: [{ type: 'text', text: 'Translate this to Japanese: Hello world' }]\n})\n\nif (task.status.state === 'completed') {\n  const reply = task.status.message?.parts\n    .filter(p => p.type === 'text')\n    .map(p => (p as { text: string }).text)\n    .join('')\n\n  console.log('Translation:', reply)\n}\n```\n\n---\n\n## Types\n\n### Protocol Types\n\n```typescript\nimport type {\n  // Tasks\n  Task,\n  TaskState,        // 'submitted' | 'working' | 'completed' | 'failed' | ...\n  TaskStatus,\n  Artifact,\n\n  // Messages\n  Message,          // { role: 'user' | 'agent', parts: Part[] }\n  Part,             // TextPart | FilePart | DataPart\n  TextPart,         // { type: 'text', text: string }\n  FilePart,         // { type: 'file', file: { name?, mimeType?, bytes?, uri? } }\n  DataPart,         // { type: 'data', data: Record<string, unknown> }\n\n  // Params\n  SendTaskParams,\n  GetTaskParams,\n  CancelTaskParams,\n  PushNotificationConfig,\n\n  // Streaming\n  TaskStatusUpdateEvent,\n  TaskArtifactUpdateEvent,\n  TaskUpdateEvent,\n\n  // JSON-RPC\n  JsonRpcRequest,\n  JsonRpcResponse,\n  JsonRpcError\n} from '@402md/a2a'\n```\n\n### Agent Card Types\n\n```typescript\nimport type {\n  A2AAgentCard,\n  A2ATransport,     // 'JSONRPC' | 'gRPC' | 'REST'\n  A2AProvider,\n  A2ACapabilities,\n  A2AAuthScheme,\n  A2ASkill,\n  ToAgentCardOptions\n} from '@402md/a2a'\n```\n\n### Error Codes\n\n```typescript\nimport { A2A_ERROR_CODES } from '@402md/a2a'\n\nA2A_ERROR_CODES.TASK_NOT_FOUND        // -32001\nA2A_ERROR_CODES.TASK_NOT_CANCELABLE   // -32002\nA2A_ERROR_CODES.UNSUPPORTED_OPERATION // -32004\nA2A_ERROR_CODES.INVALID_REQUEST       // -32600\nA2A_ERROR_CODES.METHOD_NOT_FOUND      // -32601\nA2A_ERROR_CODES.INVALID_PARAMS        // -32602\nA2A_ERROR_CODES.INTERNAL_ERROR        // -32603\nA2A_ERROR_CODES.PARSE_ERROR           // -32700\n```\n\n---\n\n## A2A Protocol Compatibility\n\nThis package targets **A2A specification v0.3.0**.\n\n| Feature | Status |\n|---------|--------|\n| Agent Card discovery (`/.well-known/agent-card.json`) | Supported |\n| `tasks/send` | Supported |\n| `tasks/get` | Supported |\n| `tasks/cancel` | Supported |\n| `tasks/sendSubscribe` (SSE streaming) | Client only |\n| `tasks/pushNotification/set` | Client only |\n| `tasks/pushNotification/get` | Client only |\n\n### Framework Support\n\n| Framework | Discovery | Handler |\n|-----------|-----------|---------|\n| Express / Connect | `serveAgentCard()` | `handleA2A()` |\n| Hono | `serveAgentCardHono()` | `handleA2A()` |\n| Next.js App Router | `agentCardResponse()` | `handleA2ANext()` |\n| Raw Node.js HTTP | `serveAgentCard()` | `handleA2A()` |\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}