npm package: @opencommerceprotocol/agent-discovery
Description: Open Commerce Protocol — Agent discovery infrastructure: serve, discover, and bridge agent tools via /.well-known/agent.json
Latest version: 1.0.0

# @opencommerceprotocol/agent-discovery

Agent discovery infrastructure for the [Open Commerce Protocol](https://opencommerceprotocol.org). Implements the AGENT_DISCOVERY_PLAN specification — both the server-side SDK for registering agent tools, and the client-side SDK for agents to discover tools at any URL.

## Installation

```bash
npm install @opencommerceprotocol/agent-discovery
```

## Server-Side: Register Agent Tools

Use `registerAgentTools` to declare your tools and auto-generate the `/.well-known/agent.json` manifest.

```typescript
import { registerAgentTools } from '@opencommerceprotocol/agent-discovery';
import { Hono } from 'hono';

const { manifest, middleware } = registerAgentTools({
  name: 'My Store',
  description: 'Agent-enabled shopping store',
  url: 'https://mystore.com',
  version: '1.0.0',
  tools: [
    {
      name: 'search_products',
      description: 'Search the product catalog',
      parameters: {
        type: 'object',
        properties: {
          query: { type: 'string', description: 'Search query' },
          limit: { type: 'number', description: 'Max results' },
        },
      },
      handler: async (params) => {
        const res = await fetch(`/api/products?q=${params.query}`);
        return res.json();
      },
    },
  ],
  auth: { type: 'none' },
  verticals: ['commerce'],
});

const app = new Hono();
middleware(app);  // serves /.well-known/agent.json and /.well-known/agent-tools
```

### `RegisterAgentToolsConfig`

| Option | Type | Description |
|--------|------|-------------|
| `name` | `string` | Site display name |
| `description` | `string` | Agent-friendly site description |
| `url` | `string` | Site base URL |
| `version` | `string` | API version |
| `tools` | `AgentToolConfig[]` | Tool definitions |
| `auth` | `AgentAuth` | Authentication config |
| `bridge` | `AgentBridge` | Protocol bridge declarations |
| `verticals` | `AgentVertical[]` | Site categories |

### `RegisterResult`

```typescript
interface RegisterResult {
  manifest: AgentManifest;       // The generated agent manifest
  middleware: HonoMiddleware;    // Hono app plugin — serves /.well-known/agent.json
  toJSON(): string;              // Manifest as JSON string
}
```

## Server-Side: Hono Middleware

If you already have an `AgentManifest`, use `agentDiscoveryMiddleware` directly:

```typescript
import { agentDiscoveryMiddleware } from '@opencommerceprotocol/agent-discovery';

const app = new Hono();
app.use(agentDiscoveryMiddleware(myManifest));
```

## Client-Side: Discover Agent Tools

```typescript
import { discoverAgent, discoverTools } from '@opencommerceprotocol/agent-discovery/client';

// Discover full agent manifest from a URL
const result = await discoverAgent('https://mystore.com');
if (result.found) {
  console.log(result.mode);      // 'direct' | 'ocp_fallback'
  console.log(result.manifest);  // AgentManifest
}

// Discover just the tool list
const tools = await discoverTools('https://mystore.com');
// AgentTool[] or empty array if not found
```

### Discovery Modes

1. **Mode A (Direct)**: Fetches `/.well-known/agent.json`
2. **Mode B (OCP Fallback)**: Falls back to `/.well-known/ocp.json` for OCP-enabled sites

### `DiscoveryResult`

```typescript
interface DiscoveryResult {
  found: boolean;
  mode?: 'direct' | 'ocp_fallback';
  manifest?: AgentManifest;
  manifest_url?: string;
}
```

## Protocol Bridge Mappers

Convert agent manifests to other protocol formats:

```typescript
import { toMCPTools, toOpenAITools, toA2ATools, toA2AAgentCard, toOpenAPISpec } from '@opencommerceprotocol/agent-discovery';

// Convert to MCP tool definitions
const mcpTools = toMCPTools(manifest.tools);

// Convert to OpenAI function-calling format
const openAITools = toOpenAITools(manifest.tools);

// Convert to Google A2A tool definitions
const a2aTools = toA2ATools(manifest.tools);

// Convert to full A2A agent card
const agentCard = toA2AAgentCard(manifest);

// Generate OpenAPI 3.0 spec
const openAPISpec = toOpenAPISpec(manifest);
```

## Security Layer

### Request Signing (HMAC-SHA256)

```typescript
import { signRequest, verifySignature } from '@opencommerceprotocol/agent-discovery';
import type { SignedHeaders } from '@opencommerceprotocol/agent-discovery';

// Agent signs outgoing requests
const headers: SignedHeaders = signRequest({
  method: 'POST',
  url: 'https://mystore.com/api/cart',
  body: JSON.stringify({ product_id: 'prod-001', quantity: 1 }),
  apiKey: 'my-api-key',
  secret: 'my-secret',
});
// headers: { 'X-OCP-Signature': '...', 'X-OCP-Timestamp': '...' }

// Server verifies incoming request
const valid = await verifySignature({
  method: 'POST',
  url: 'https://mystore.com/api/cart',
  body: rawBody,
  secret: 'my-secret',
  headers: req.headers,
});
```

### Domain Verification

```typescript
import { generateDomainVerificationTokens, verifyDomainOwnership } from '@opencommerceprotocol/agent-discovery';

// Generate verification tokens for a domain
const tokens = generateDomainVerificationTokens('mystore.com');
// tokens.file_token — place at /.well-known/agent-verify.txt
// tokens.dns_token — add as DNS TXT record

// Verify a domain (agent-side)
const verified = await verifyDomainOwnership('mystore.com', tokens.file_token);
```

### OAuth2 Client Credentials

```typescript
import { fetchOAuth2Token } from '@opencommerceprotocol/agent-discovery';
import type { OAuth2ClientConfig } from '@opencommerceprotocol/agent-discovery';

const config: OAuth2ClientConfig = {
  clientId: 'my-client-id',
  clientSecret: 'my-client-secret',
  tokenUrl: 'https://mystore.com/oauth/token',
  scopes: ['commerce:read', 'commerce:cart'],
};

const token = await fetchOAuth2Token(config);
// Use token.access_token in Authorization header
```

### Rate Limit Parsing

```typescript
import { parseRateLimit } from '@opencommerceprotocol/agent-discovery';
import type { RateLimitPolicy } from '@opencommerceprotocol/agent-discovery';

const policy: RateLimitPolicy = parseRateLimit(
  response.headers.get('RateLimit-Policy')
);
// { requestsPerWindow: 100, windowSecs: 3600, retryAfterSecs?: 60 }
```

## Manifest Validation

```typescript
import { validateManifest, isAgentManifest } from '@opencommerceprotocol/agent-discovery';

// Type guard
if (isAgentManifest(data)) {
  // data is AgentManifest
}

// Full validation
const result = validateManifest(data);
// { valid: boolean, errors: ValidationError[], warnings: ValidationWarning[] }
```

## Key Types

```typescript
import type {
  AgentManifest,
  AgentTool,
  AgentToolParameters,
  AgentAuth,          // { type: 'none' | 'api_key' | 'oauth2' | 'bearer' }
  OAuth2Config,
  ApiKeyConfig,
  AgentBridge,        // { mcp?, openai?, a2a?, openapi? }
  AgentVertical,      // 'commerce' | 'travel' | 'knowledge' | 'saas' | ...
} from '@opencommerceprotocol/agent-discovery';
```