# Introduction

Welcome to the vCon MCP Server documentation!

## What is vCon MCP Server?

The vCon MCP Server is a production-ready server that implements the IETF vCon (Virtual Conversation) standard and provides AI assistants with the ability to manage, search, and analyze conversation data through the Model Context Protocol (MCP).

## Key Features

* **IETF vCon Compliant** - Fully implements the draft-ietf-vcon-vcon-core-02 specification
* **AI-Ready** - MCP tools for seamless integration with Claude, ChatGPT, and other AI assistants
* **Advanced Search** - Four search modes including semantic search with AI embeddings
* **Tag System** - Flexible key-value metadata for organizing conversations
* **Plugin Architecture** - Extensible for custom functionality and compliance features
* **Type-Safe** - Full TypeScript implementation with Zod validation
* **Production-Ready** - Comprehensive testing, monitoring, and deployment guides

## What is vCon?

vCon (Virtual Conversation) is an IETF standard for representing conversations in a portable, interoperable format. It's like "PDF for conversations" - a standardized container that includes:

* **Conversations** from any medium (voice, video, text, email)
* **Participants** with identity information
* **AI Analysis** results (transcription, sentiment, summaries)
* **Attachments** (documents, images, files)
* **Privacy markers** for consent and redaction

### Why vCon?

**Portability** - Move conversation data between systems without vendor lock-in

**Interoperability** - Standard format works across tools and platforms

**Privacy-Ready** - Built-in support for consent tracking and data redaction

**AI-Friendly** - Structured format perfect for AI analysis and processing

## What is MCP?

The Model Context Protocol (MCP) is an open standard that enables AI assistants to interact with external tools and data sources. Instead of AI assistants being limited to their training data, MCP allows them to:

* Access real-time data from databases and APIs
* Perform actions using external tools
* Read and write to external systems
* Maintain context across conversations

### MCP + vCon = Powerful Combination

By combining MCP with vCon, AI assistants can:

* **Create** conversation records from transcripts or recordings
* **Search** through historical conversations
* **Analyze** conversations for insights and patterns
* **Tag** conversations for organization
* **Extract** information from past interactions

## Use Cases

### Contact Centers

* Store and search customer interactions
* Analyze agent performance
* Track issue resolution
* Generate compliance reports

### Sales Teams

* Record sales calls and meetings
* Extract action items automatically
* Analyze successful conversation patterns
* Generate meeting summaries

### Research

* Build conversation datasets
* Study communication patterns
* Train ML models
* Analyze language use

### Healthcare

* Document patient consultations
* Maintain HIPAA-compliant records
* Track consent and permissions
* Generate clinical summaries

### Legal & Compliance

* Maintain conversation archives
* Apply redaction for privacy
* Track consent history
* Generate audit trails

## Architecture Overview

```
┌─────────────────────┐
│   AI Assistant      │  (Claude, ChatGPT, etc.)
│   (MCP Client)      │
└──────────┬──────────┘
           │ MCP Protocol (stdio/HTTP)
           │
┌──────────▼──────────┐
│   vCon MCP Server   │  (This project)
│                     │
│  ┌───────────────┐  │
│  │ MCP Tools     │  │  - Create, read, update, delete
│  │               │  │  - Search (4 modes)
│  │               │  │  - Tag management
│  └───────┬───────┘  │  - Templates & schemas
│          │          │
│  ┌───────▼───────┐  │
│  │ Plugin System │  │  - Custom extensions
│  │               │  │  - Privacy & compliance
│  └───────┬───────┘  │  - Access control
│          │          │
│  ┌───────▼───────┐  │
│  │ Database      │  │  - CRUD operations
│  │ Queries       │  │  - Search indexing
│  └───────┬───────┘  │  - Tag filtering
│          │          │
└──────────┼──────────┘
           │ Supabase Client
           │
┌──────────▼──────────┐
│    Supabase         │
│  (PostgreSQL)       │
│                     │
│  ┌───────────────┐  │
│  │ vCon Tables   │  │  - Normalized schema
│  │               │  │  - Optimized indexes
│  └───────────────┘  │  - Foreign keys
│  ┌───────────────┐  │
│  │ pgvector      │  │  - AI embeddings
│  │ (Embeddings)  │  │  - Semantic search
│  └───────────────┘  │
└─────────────────────┘
```

## Next Steps

Ready to get started? Follow our guides:

1. [**Installation**](/guide/installation) - Complete installation guide
2. [**Basic Usage**](/guide/basic-usage) - Learn the core operations
3. [**Getting Started**](/guide/getting-started) - Quick start for developers
4. [**Search Guide**](/guide/search) - Master the search capabilities
5. [**Tag Management**](/guide/tags) - Organize your conversations
6. [**Prompts Guide**](/guide/prompts) - Understand query prompts
7. [**Database Tools**](/guide/database-tools) - Inspect your database

## Documentation Structure

* **Guide** - User-friendly tutorials and how-tos
* **API Reference** - Detailed tool and type documentation
* **Development** - Build, extend, and contribute
* **Deployment** - Production setup and best practices
* **Reference** - IETF specification and technical details
* **Examples** - Code examples and integration patterns

## Getting Help

* 📖 Check the [Troubleshooting Guide](/guide/troubleshooting)
* 💬 Ask in [GitHub Discussions](https://github.com/vcon-dev/vcon-mcp/discussions)
* 🐛 Report bugs in [GitHub Issues](https://github.com/vcon-dev/vcon-mcp/issues)
* 📧 Contact the team at <support@example.com>

## Contributing

We welcome contributions! See our [Contributing Guide](/development/contributing) for details on:

* Reporting bugs
* Suggesting features
* Submitting pull requests
* Writing documentation

## License

This project is released under the MIT License. See the [LICENSE](https://github.com/vcon-dev/vcon-mcp/blob/main/LICENSE/README.md) file for details.


# Getting Started

> **Quick start guide to understand and build this project**

## 🎯 What Is This Project?

This project provides:

1. **Complete Documentation** for building an IETF vCon-compliant MCP server
2. **Corrections** to common implementation mistakes in the spec
3. **Step-by-step Build Guide** to implement from scratch
4. **Reference Materials** from IETF vCon working group

## 📚 Start Here

### New to vCon?

**Read in this order:**

1. [**README.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/README.md) (5 min)
   * Overview of the project
   * Documentation structure
   * Critical corrections summary
2. [**QUICK\_REFERENCE.md**](/reference/quick_reference) (5 min)
   * Critical field corrections
   * Common mistakes to avoid
   * Quick checklist
3. [**CLAUDE.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/CLAUDE.md) (15 min)
   * Complete implementation guide for AI-assisted development
   * Corrected TypeScript types and patterns
   * Database schema and queries

### Already Know vCon?

**Fast track:**

1. [**IMPLEMENTATION\_CORRECTIONS.md**](/reference/implementation_corrections) (15 min)
   * All 7 critical spec issues
   * What was wrong vs. what's correct
   * Why each correction matters
2. [**CLAUDE.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/CLAUDE.md) (30 min)
   * Complete implementation guide
   * Corrected TypeScript types
   * Database schema and queries
   * MCP tool definitions

### Migrating Existing Code?

1. [**MIGRATION\_GUIDE.md**](/reference/migration_guide) (30 min)
   * Database migration SQL
   * Code refactoring steps
   * Verification queries
2. [**QUICK\_REFERENCE.md**](/reference/quick_reference)
   * Use as checklist while migrating

## 🔴 Critical Corrections

**⚠️ These are MANDATORY for IETF spec compliance:**

### 1. Analysis Schema Field

```typescript
// ❌ WRONG
interface Analysis {
  schema_version?: string;
}

// ✅ CORRECT
interface Analysis {
  schema?: string;
}
```

### 2. Analysis Vendor Requirement

```typescript
// ❌ WRONG
interface Analysis {
  vendor?: string;  // Optional
}

// ✅ CORRECT
interface Analysis {
  vendor: string;  // Required
}
```

### 3. Analysis Body Type

```typescript
// ❌ WRONG
interface Analysis {
  body: object;  // Only supports JSON
}

// ✅ CORRECT
interface Analysis {
  body?: string;  // Supports any format
}
```

**See** [**QUICK\_REFERENCE.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/QUICK_REFERENCE.md) **for all 7 corrections.**

## 🚀 Quick Setup (5 Minutes)

### Prerequisites

* Node.js 18+ installed
* Supabase account (free tier works)
* Git installed

### Setup Steps

```bash
# 1. Clone or create project directory
mkdir vcon-mcp-server && cd vcon-mcp-server

# 2. Initialize project
npm init -y

# 3. Install dependencies
npm install @modelcontextprotocol/sdk @supabase/supabase-js zod
npm install -D typescript @types/node tsx vitest

# 4. Copy example configuration
# Use the tsconfig.json and package.json from the Building Guide

# 5. Create .env file
echo "SUPABASE_URL=your-url" > .env
echo "SUPABASE_ANON_KEY=your-key" >> .env

# 6. Follow the Building Guide from Phase 2 onwards
```

## 📖 Documentation Map

```
Start Here
    ├── README.md ────────────────────► Master index & navigation
    │
    ├── docs/guide/getting-started.md ► You are here!
    │
    └── Choose your path:
        │
        ├── New Implementation ─────────────┐
        │   ├── docs/reference/QUICK_REF    │
        │   ├── CLAUDE.md ──────────────────┼──► Primary path
        │   └── docs/reference/CORRECTED_   │
        │       SCHEMA.md ─────────────────-┘
        │
        ├── Migration ──────────────────────┐
        │   ├── IMPLEMENTATION_CORRECTIONS  │
        │   ├── docs/reference/MIGRATION ───┼──► Fix existing code
        │   └── docs/reference/CORRECTED_   │
        │       SCHEMA.md ─────────────────-┘
        │
        └── Deep Dive ──────────────────────┐
            ├── docs/reference/vcon-spec.md │
            └── background_docs/ ───────────┘

```

## 🎓 Learning Paths

### Path 1: Complete Beginner (6 hours)

**Goal:** Build a working vCon MCP server from scratch

1. Read background material (1 hour)
   * `background_docs/vcon_quickstart_guide.md`
   * `background_docs/draft-ietf-vcon-vcon-core-02.txt` (introduction)
2. Understand corrections (30 min)
   * `docs/reference/QUICK_REFERENCE.md`
   * `docs/reference/IMPLEMENTATION_CORRECTIONS.md`
3. Follow the implementation guide (4 hours)
   * `CLAUDE.md` — complete patterns, types, and DB schema
4. Test and verify (30 min)
   * Run `npm test`
   * Test with AI assistant

### Path 2: Experienced Developer (2 hours)

**Goal:** Implement spec-compliant vCon server quickly

1. Review corrections (15 min)
   * `docs/reference/QUICK_REFERENCE.md`
2. Study implementation (30 min)
   * `CLAUDE.md`
3. Build core (1 hour)
   * Database schema
   * TypeScript types
   * Database queries
4. Add MCP layer (15 min)
   * Tool definitions
   * Server setup

### Path 3: Migration (3 hours)

**Goal:** Fix existing implementation to match spec

1. Identify issues (30 min)
   * `docs/reference/IMPLEMENTATION_CORRECTIONS.md`
   * Compare with your code
2. Plan migration (30 min)
   * `docs/reference/MIGRATION_GUIDE.md`
   * Backup database and code
3. Execute migration (1.5 hours)
   * Database schema changes
   * Code refactoring
   * Update tests
4. Verify (30 min)
   * Run verification queries
   * Run `npm test`
   * Manual review

### Path 4: AI-Assisted Build (30 min + AI time)

**Goal:** Use Claude Code to build for you

1. Prepare instructions (15 min)
   * Read `docs/reference/QUICK_REFERENCE.md`
   * Set up Supabase
2. Provide to AI (5 min)

   ```
   Build an IETF vCon MCP server following the specifications in:
   - CLAUDE.md
   - docs/reference/CORRECTED_SCHEMA.md
   - docs/reference/QUICK_REFERENCE.md (for checklist)

   Use the corrected field names and ensure full spec compliance.
   ```
3. Review & test (10 min)
   * Verify no `schema_version` in code
   * Check vendor is required
   * Run `npm test`

## 🛠️ What You'll Build

### Core Components

1. **TypeScript Types** (`src/types/vcon.ts`)
   * All IETF vCon objects
   * Corrected field names
   * Type validation helpers
2. **Database Layer** (`src/db/`)
   * Supabase client
   * CRUD operations
   * Search queries
3. **MCP Server** (`src/index.ts`)
   * Tool definitions
   * Request handlers
   * Error handling
4. **Utilities** (`src/utils/`)
   * vCon validation
   * Privacy helpers
   * Serialization

### MCP Tools Provided (46 tools)

* **CRUD:** `create_vcon`, `get_vcon`, `update_vcon`, `delete_vcon`, `add_party`, `add_dialog`, `add_analysis`, `add_attachment`, `create_vcon_from_template`
* **Sub-resource update/remove:** `update_party`, `remove_party`, `update_dialog`, `remove_dialog`, `update_analysis`, `remove_analysis`, `update_attachment`, `remove_attachment`
* **Search:** `search_vcons`, `search_vcons_content`, `search_vcons_semantic`, `search_vcons_hybrid`
* **Contract:** `vcon_fetch`, `vcon_search`, `vcon_capabilities`, `vcon_taxonomy`, `vcon_aggregate`, `vcon_graph_shape`, `describe_response_shape`
* **Tags:** `manage_tag`, `get_tags`, `remove_all_tags`, `search_by_tags`, `get_unique_tags`
* **Analytics:** `get_database_analytics`, `get_monthly_growth_analytics`, `get_content_analytics`, `get_tag_analytics`, `get_attachment_analytics`, `get_database_health_metrics`
* **Database:** `get_database_shape`, `get_database_stats`, `analyze_query`, `get_database_size_info`, `get_smart_search_limits`
* **Schema:** `get_schema`, `get_examples`

### REST API

All MCP tools are also available as REST endpoints at `/api/v1` when running in HTTP transport mode. See the [REST API Reference](/api-reference/rest-api) for details.

### Database Schema

* `vcons` - Main vCon records
* `parties` - Conversation participants
* `dialog` - Recordings, texts, transfers
* `analysis` - AI/ML analysis results
* `attachments` - File attachments
* `party_history` - Event timeline

## 📋 Pre-Build Checklist

Before you start building:

* [ ] Read README.md
* [ ] Read QUICK\_REFERENCE.md
* [ ] Understand the 7 critical corrections
* [ ] Have Supabase account ready
* [ ] Have Node.js 18+ installed
* [ ] Have code editor ready
* [ ] Have 4-6 hours available for first build

## ⚠️ Common Pitfalls

### Mistake #1: Using Wrong Field Names

```typescript
// ❌ DON'T
const analysis = { schema_version: '1.0' };

// ✅ DO
const analysis = { schema: '1.0' };
```

### Mistake #2: Making Vendor Optional

```typescript
// ❌ DON'T
interface Analysis { vendor?: string; }

// ✅ DO
interface Analysis { vendor: string; }
```

### Mistake #3: Wrong Body Type

```typescript
// ❌ DON'T
body: object  // Database: JSONB

// ✅ DO
body?: string  // Database: TEXT
```

### Mistake #4: Adding Default Values

```sql
-- ❌ DON'T
encoding TEXT DEFAULT 'json'

-- ✅ DO
encoding TEXT CHECK (encoding IN ('base64url', 'json', 'none'))
```

### Mistake #5: Forgetting New Fields

```typescript
// ❌ MISSING
interface Party {
  name?: string;
  // missing: uuid, did
}

// ✅ COMPLETE
interface Party {
  name?: string;
  uuid?: string;
  did?: string;
}
```

## 🧪 Testing Your Implementation

### Quick Compliance Check

```bash
# 1. Check for wrong field names
grep -r "schema_version" src/
# Should return nothing

# 2. Check vendor is not optional
grep "vendor?" src/types/vcon.ts
# Should return nothing

# 3. Run tests
npm test
# Should pass

# 4. Check database schema
# Run verification queries from docs/reference/CORRECTED_SCHEMA.md
```

### Integration Test

Create a test vCon:

```typescript
const vcon: VCon = {
  vcon: '0.4.0',
  uuid: crypto.randomUUID(),
  created_at: new Date().toISOString(),
  parties: [{
    name: 'Alice',
    mailto: 'alice@example.com',
    uuid: crypto.randomUUID()
  }],
  analysis: [{
    type: 'sentiment',
    vendor: 'TestVendor',  // Required
    schema: 'v1.0',        // Correct field name
    body: JSON.stringify({ score: 0.8 }),
    encoding: 'json'
  }]
};

// Validate
const result = validateVCon(vcon);
console.log(result.valid ? '✅ Valid' : '❌ Invalid');
```

## 📞 Getting Help

### Documentation Questions

* Check [README.md](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/README.md) troubleshooting section
* Search for your error in the [Building Guide](/development/building)
* Review relevant correction in [IMPLEMENTATION\_CORRECTIONS.md](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/IMPLEMENTATION_CORRECTIONS.md)

### Spec Questions

* Consult `background_docs/draft-ietf-vcon-vcon-core-02.txt`
* Cross-reference section numbers in correction docs
* Cross-reference the [Implementation Corrections](/reference/implementation_corrections) for before/after examples

### Implementation Questions

* Follow [CLAUDE.md](https://github.com/vcon-dev/vcon-mcp/tree/main/CLAUDE.md) step-by-step
* Use code examples from the [Building Guide](/development/building)
* Check [MIGRATION\_GUIDE.md](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/MIGRATION_GUIDE.md) for specific fixes

## 🎯 Success Criteria

Your implementation is successful when:

* [x] Git repository initialized
* [ ] All dependencies installed
* [ ] TypeScript compiles without errors
* [ ] Database schema matches spec
* [ ] No `schema_version` anywhere in code
* [ ] Analysis.vendor is required (not optional)
* [ ] Analysis.body is string type
* [ ] All compliance tests pass
* [ ] MCP server starts and lists tools
* [ ] Can create spec-compliant vCons
* [ ] Can add analysis with correct fields
* [ ] vCons are interoperable

## 🚀 Next Actions

**Choose your path:**

### I'm Ready to Build

→ Read [**CLAUDE.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/CLAUDE.md) and follow the patterns there

### I Need to Understand Corrections First

→ Read [**IMPLEMENTATION\_CORRECTIONS.md**](/reference/implementation_corrections)

### I'm Migrating Existing Code

→ Follow [**MIGRATION\_GUIDE.md**](/reference/migration_guide)

### I Want the Quick Version

→ Read [**QUICK\_REFERENCE.md**](/reference/quick_reference) then dive into [**CLAUDE.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/CLAUDE.md)

***

## 📊 Project Status

✅ **Complete:**

* Git repository initialized
* All documentation created
* Build guide written
* Example code provided

⏳ **Next Steps:**

* Follow the Building Guide to implement
* Run compliance tests
* Deploy MCP server

***

**Ready?** Start with [**CLAUDE.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/CLAUDE.md)

**Questions?** Check [**README.md**](https://github.com/vcon-dev/vcon-mcp/tree/main/README.md) → Troubleshooting

**Need quick reference?** Use [**QUICK\_REFERENCE.md**](/reference/quick_reference)

***

*Last Updated: June 2026*\
*Project: vCon MCP Server Documentation v1.2.0*\
*Spec: draft-ietf-vcon-vcon-core-02 (v0.4.0)*


# Installation

Complete guide to installing and setting up the vCon MCP Server.

## Prerequisites

Before you begin, ensure you have the following installed:

### Required

* **Node.js** 18.0 or higher
  * Check version: `node --version`
  * Download: [nodejs.org](https://nodejs.org/)
* **npm** 9.0 or higher (comes with Node.js)
  * Check version: `npm --version`
* **Git** (for cloning the repository)
  * Check version: `git --version`
  * Download: [git-scm.com](https://git-scm.com/)
* **Supabase Account** (free tier available)
  * Sign up: [supabase.com](https://supabase.com)

### Optional

* **OpenAI API Key** (for semantic search with embeddings)
  * Sign up: [platform.openai.com](https://platform.openai.com/)
* **Claude Desktop** (for using the server with Claude AI)
  * Download: [claude.ai/download](https://claude.ai/download)

***

## Installation Methods

Choose the installation method that best fits your needs:

* [Method 1: Quick Install (Recommended)](#method-1-quick-install-recommended)
* [Method 2: Development Install](#method-2-development-install)
* [Method 3: npm Global Install](#method-3-npm-global-install)
* [Method 4: Docker Install](#method-4-docker-install)

***

## Method 1: Quick Install (Recommended)

Perfect for getting started quickly with the server.

### Step 1: Clone the Repository

```bash
# Clone from GitHub
git clone https://github.com/vcon-dev/vcon-mcp.git
cd vcon-mcp

# Or if using a different repository
git clone YOUR_REPOSITORY_URL
cd vcon-mcp
```

### Step 2: Install Dependencies

```bash
npm install
```

This will install all required dependencies:

* `@modelcontextprotocol/sdk` - MCP protocol implementation
* `@supabase/supabase-js` - Supabase client
* `zod` - Runtime validation
* Development tools (TypeScript, Vitest, etc.)

### Step 3: Set Up Environment Variables

```bash
# Copy the example environment file
cp .env.example .env

# Edit the .env file with your credentials
nano .env  # or use your preferred editor
```

Configure the following required variables:

```env
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key-here
```

If you expose the HTTP transport (REST API and MCP over HTTP), also set API keys:

```env
# Full access: read, write, delete
API_KEYS=ops-key-1
# Read-only: GET-only on REST, no write MCP tools. Give these to consumers.
API_KEYS_READONLY=partner-key-1
```

`API_KEYS` tokens can delete the whole corpus, so hand out `API_KEYS_READONLY` tokens to anyone who only needs to read. See [Configuration → API Keys and Read-Only Access](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/configuration.md#api-keys-and-read-only-access).

**Getting Supabase Credentials:**

1. Go to [supabase.com](https://supabase.com) and sign in
2. Create a new project (or select existing)
3. Go to **Settings** → **API**
4. Copy the **Project URL** to `SUPABASE_URL`
5. Copy the **anon public** key to `SUPABASE_ANON_KEY`

### Step 4: Set Up Database Schema

Run the database migrations to create the required tables:

```bash
# Option A: Using Supabase CLI (recommended)
npx supabase db push

# Option B: Manual via Supabase Dashboard
# 1. Go to your Supabase project
# 2. Navigate to SQL Editor
# 3. Run the migration files from supabase/migrations/ in order
```

**Migration files included:**

* `001_initial_schema.sql` - Core vCon tables
* `002_indexes.sql` - Performance indexes
* `003_rls_policies.sql` - Row-level security
* `004_search_functions.sql` - Full-text search
* `005_vector_extension.sql` - Semantic search (optional)

### Step 5: Build the Project

```bash
npm run build
```

This compiles TypeScript to JavaScript in the `dist/` directory.

### Step 6: Verify Installation

```bash
# Run tests to verify everything works
npm test

# Run compliance tests
npm run test:compliance
```

✅ **Installation complete!** Proceed to [Basic Usage](/guide/basic-usage).

***

## Method 2: Development Install

For developers who want to contribute or modify the code.

### Step 1: Fork and Clone

```bash
# Fork the repository on GitHub first
# Then clone your fork
git clone https://github.com/YOUR_USERNAME/vcon-mcp.git
cd vcon-mcp

# Add upstream remote
git remote add upstream https://github.com/vcon-dev/vcon-mcp.git
```

### Step 2: Install with Dev Dependencies

```bash
npm install
```

### Step 3: Set Up Environment

```bash
cp .env.example .env
# Edit .env with your credentials
```

### Step 4: Set Up Database

```bash
# Install Supabase CLI
npm install -g supabase

# Link to your project
supabase link --project-ref your-project-ref

# Push migrations
supabase db push

# Generate TypeScript types from database
supabase gen types typescript --local > src/types/database.ts
```

### Step 5: Start Development Server

```bash
npm run dev
```

This starts the server in watch mode - changes will reload automatically.

### Step 6: Run Tests in Watch Mode

```bash
npm test -- --watch
```

***

## Method 3: npm Global Install

Install the server globally to use from anywhere (coming soon).

```bash
# Install globally from npm
npm install -g vcon-mcp

# Create a configuration file
mkdir ~/.vcon-mcp
cat > ~/.vcon-mcp/config.json <<EOF
{
  "supabaseUrl": "https://your-project.supabase.co",
  "supabaseKey": "your-anon-key"
}
EOF

# Run the server
vcon-mcp-server
```

***

## Method 4: Docker Install

Use Docker for containerized deployment. The vCon MCP Server is available on ECR Public.

### Quick Start

```bash
# Pull the image
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main

# Run the server
docker run -d -p 3000:3000 \
  -e SUPABASE_URL=https://your-project.supabase.co \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

### Available Image Tags

| Tag                 | Description                            |
| ------------------- | -------------------------------------- |
| `main`              | Latest stable build from main branch   |
| `main-<sha>`        | Specific commit (e.g., `main-abc1234`) |
| `1.2.3`, `1.2`, `1` | Semantic version releases              |

### Running Scripts

The Docker image includes utility scripts:

```bash
# Show help and available commands
docker run --rm public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main help

# Check database status
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main script check-db-status

# Run embeddings
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e OPENAI_API_KEY=your-openai-key \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main script embed-vcons --provider=openai
```

### Docker Compose

```yaml
version: '3.8'
services:
  vcon-mcp:
    image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    ports:
      - "3000:3000"
    environment:
      - SUPABASE_URL=${SUPABASE_URL}
      - SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
      - SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - MCP_HTTP_STATELESS=true
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:3000/api/v1/health"]
      interval: 30s
      timeout: 10s
      retries: 3
```

### Connecting to Local Services

When connecting to services running on your host machine (like local Supabase):

```bash
docker run -d -p 3000:3000 \
  -e SUPABASE_URL=http://host.docker.internal:54321 \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

### Build Locally (Optional)

```bash
# Build from source
docker build -t vcon-mcp .

# Run local build
docker run -d -p 3000:3000 --env-file .env vcon-mcp
```

For complete Docker documentation, see the [Docker Deployment Guide](/deployment/docker).

***

## Configuring Claude Desktop

To use the vCon MCP Server with Claude Desktop:

### Step 1: Locate Config File

The Claude Desktop configuration file location depends on your OS:

* **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
* **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
* **Linux**: `~/.config/Claude/claude_desktop_config.json`

### Step 2: Edit Configuration

Add the vCon MCP Server to your configuration:

```json
{
  "mcpServers": {
    "vcon": {
      "command": "node",
      "args": [
        "/absolute/path/to/vcon-mcp/dist/index.js"
      ],
      "env": {
        "SUPABASE_URL": "https://your-project.supabase.co",
        "SUPABASE_ANON_KEY": "your-anon-key-here"
      }
    }
  }
}
```

**Important:** Use the **absolute path** to your `dist/index.js` file.

To find the absolute path:

```bash
# In the vcon-mcp directory
pwd
# Example output: /Users/yourname/projects/vcon-mcp

# Your path will be: /Users/yourname/projects/vcon-mcp/dist/index.js
```

### Step 3: Restart Claude Desktop

1. Quit Claude Desktop completely
2. Reopen Claude Desktop
3. Start a new conversation
4. The vCon tools should now be available

### Step 4: Verify in Claude

Ask Claude:

```
What MCP tools do you have access to?
```

You should see vCon tools listed like:

* `create_vcon`
* `get_vcon`
* `search_vcons`
* `add_analysis`
* And more...

***

## Optional: Semantic Search Setup

To enable AI-powered semantic search:

### Step 1: Enable pgvector Extension

In your Supabase SQL Editor:

```sql
-- Enable pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;

-- Verify installation
SELECT * FROM pg_extension WHERE extname = 'vector';
```

### Step 2: Run Vector Migrations

```bash
# In Supabase SQL Editor, run:
supabase/migrations/005_vector_extension.sql
supabase/migrations/006_embeddings_table.sql
```

### Step 3: Add OpenAI API Key

```bash
# Add to your .env file
echo "OPENAI_API_KEY=sk-your-openai-api-key" >> .env
```

### Step 4: Generate Embeddings (Optional)

If you have existing vCons, generate embeddings:

```bash
npm run scripts/generate-embeddings-v2.ts
```

Now you can use semantic search tools like `search_vcons_semantic` and `search_vcons_hybrid`.

***

## Troubleshooting

### Error: "Cannot find module 'dotenv'"

**Solution:** Install dependencies

```bash
npm install
```

### Error: "ENOENT: no such file or directory"

**Solution:** Make sure you built the project

```bash
npm run build
```

### Error: "Invalid Supabase URL"

**Solution:** Check your `.env` file:

```bash
# Verify .env exists
cat .env

# Verify format (no quotes needed)
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=eyJ...
```

### Error: "relation 'vcons' does not exist"

**Solution:** Run database migrations

```bash
# Using Supabase CLI
npx supabase db push

# Or manually in Supabase Dashboard SQL Editor
```

### Error: "Permission denied" when running scripts

**Solution:** Make scripts executable

```bash
chmod +x scripts/*.sh
```

### Claude Desktop doesn't show vCon tools

**Checklist:**

1. ✅ Built the project (`npm run build`)
2. ✅ Used absolute path in config
3. ✅ Restarted Claude Desktop completely
4. ✅ .env file in project root
5. ✅ Valid Supabase credentials

**Debug:**

```bash
# Test server directly
node dist/index.js

# Should output MCP initialization messages
# Press Ctrl+C to stop
```

### Tests failing

```bash
# Clean and rebuild
rm -rf node_modules dist
npm install
npm run build

# Run tests with verbose output
npm test -- --reporter=verbose
```

### Database connection issues

```bash
# Test Supabase connection
curl "https://your-project.supabase.co/rest/v1/" \
  -H "apikey: your-anon-key"

# Should return 200 OK
```

***

## Environment Variables Reference

Complete list of supported environment variables:

Embedding provider priority: **LiteLLM → Azure OpenAI → OpenAI → Hugging Face** (first configured wins).

| Variable                          | Required | Description                                                                                                                                                                                                                         | Default           |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------- |
| `SUPABASE_URL`                    | ✅ Yes    | Your Supabase project URL                                                                                                                                                                                                           | -                 |
| `SUPABASE_ANON_KEY`               | ✅ Yes    | Supabase anon public key                                                                                                                                                                                                            | -                 |
| `SUPABASE_SERVICE_ROLE_KEY`       | ❌ No     | Service role key (admin operations)                                                                                                                                                                                                 | -                 |
| `SUPABASE_DB_SCHEMA`              | ❌ No     | Postgres schema this instance is scoped to. Set a per-group schema for schema isolation in a shared project — see [Multi-Supabase Isolation](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/multi-supabase-isolation.md) | `public`          |
| `ENV_FILE`                        | ❌ No     | Env file to load instead of `.env` (e.g. `.env.sales`), for per-group launchers                                                                                                                                                     | `.env`            |
| `VCON_INSTANCE_LABEL`             | ❌ No     | Free-text label for this instance's group; surfaced in logs and `GET /health`                                                                                                                                                       | -                 |
| `LITELLM_PROXY_URL`               | ❌ No     | LiteLLM proxy base URL — takes priority for embeddings                                                                                                                                                                              | -                 |
| `LITELLM_MASTER_KEY`              | ❌ No     | LiteLLM proxy API key (also accepted as `LITELLM_API_KEY`)                                                                                                                                                                          | -                 |
| `OPENAI_API_KEY`                  | ❌ No     | OpenAI API key for embeddings (if LiteLLM not set)                                                                                                                                                                                  | -                 |
| `AZURE_OPENAI_EMBEDDING_ENDPOINT` | ❌ No     | Azure OpenAI base endpoint (e.g., <https://your-resource.openai.azure.com>)                                                                                                                                                         | -                 |
| `AZURE_OPENAI_EMBEDDING_API_KEY`  | ❌ No     | Azure OpenAI API key                                                                                                                                                                                                                | -                 |
| `HF_API_TOKEN`                    | ❌ No     | Hugging Face API token for embeddings (lowest priority fallback)                                                                                                                                                                    | -                 |
| `VCON_PLUGINS_PATH`               | ❌ No     | Comma-separated plugin paths                                                                                                                                                                                                        | -                 |
| `VCON_LICENSE_KEY`                | ❌ No     | Enterprise license key                                                                                                                                                                                                              | -                 |
| `MCP_SERVER_NAME`                 | ❌ No     | Server name for MCP                                                                                                                                                                                                                 | `vcon-mcp-server` |
| `LOG_LEVEL`                       | ❌ No     | Logging level (debug/info/warn/error)                                                                                                                                                                                               | `info`            |

***

## Verifying Your Installation

### Quick Verification Script

```bash
# Create a test script
cat > test-installation.sh <<'EOF'
#!/bin/bash

echo "=== vCon MCP Server Installation Check ==="
echo ""

# Check Node.js
echo "✓ Checking Node.js..."
node --version

# Check npm
echo "✓ Checking npm..."
npm --version

# Check if built
echo "✓ Checking build..."
if [ -f "dist/index.js" ]; then
  echo "  Build found: dist/index.js"
else
  echo "  ❌ Build not found. Run: npm run build"
fi

# Check .env
echo "✓ Checking environment..."
if [ -f ".env" ]; then
  echo "  .env file found"
else
  echo "  ❌ .env file missing. Run: cp .env.example .env"
fi

# Run tests
echo "✓ Running tests..."
npm test -- --run

echo ""
echo "=== Installation check complete ==="
EOF

chmod +x test-installation.sh
./test-installation.sh
```

### Manual Verification

```bash
# 1. Check Node.js version (18+)
node --version

# 2. Check npm version (9+)
npm --version

# 3. Check dependencies installed
npm list --depth=0

# 4. Check build exists
ls -la dist/index.js

# 5. Check environment file
cat .env

# 6. Run compliance tests
npm run test:compliance

# 7. Test server startup
node dist/index.js
# Press Ctrl+C to stop after seeing initialization messages
```

***

## Updating

To update to the latest version:

```bash
# Pull latest changes
git pull origin main

# Install any new dependencies
npm install

# Rebuild
npm run build

# Run migrations (if any)
npx supabase db push

# Test
npm test
```

***

## Uninstalling

To completely remove the vCon MCP Server:

```bash
# 1. Remove Claude Desktop configuration
# Edit ~/Library/Application Support/Claude/claude_desktop_config.json
# Remove the "vcon" entry from mcpServers

# 2. Remove project directory
cd ..
rm -rf vcon-mcp

# 3. (Optional) Remove database in Supabase
# Go to Supabase Dashboard → Settings → General → Delete Project
```

***

## Next Steps

Once installation is complete:

1. [**Basic Usage Guide**](/guide/basic-usage) - Learn to use the server
2. [**Search Guide**](/guide/search) - Master search capabilities
3. [**Tag Management**](/guide/tags) - Organize your vCons
4. [**API Reference**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/api/README.md) - Detailed tool documentation

***

## Getting Help

If you encounter issues:

1. **Check** [Troubleshooting](#troubleshooting) section above
2. **Search** [GitHub Issues](https://github.com/vcon-dev/vcon-mcp/issues)
3. **Ask** in [GitHub Discussions](https://github.com/vcon-dev/vcon-mcp/discussions)
4. **Report** bugs with detailed error messages

***

**Installation successful?** Continue to [Basic Usage](/guide/basic-usage) →


# Basic Usage

Learn how to use the vCon MCP Server with AI assistants and common workflows.

## Prerequisites

Before starting, ensure you have:

* ✅ Completed [Installation](/guide/installation)
* ✅ Configured Claude Desktop or another MCP client
* ✅ Database migrations applied
* ✅ Valid Supabase credentials in `.env`

***

## Quick Start

### Your First vCon

Let's create your first vCon using Claude Desktop:

**1. Ask Claude:**

```
Create a vCon for a customer support call between Alice (agent) 
and Bob (customer) discussing a refund request.
```

**Claude will:**

* Use the `create_vcon` tool
* Create parties for Alice and Bob
* Set subject to describe the call
* Return the vCon UUID

**2. View the vCon:**

```
Show me the vCon you just created
```

**3. Add a transcript:**

```
Add a text dialog to this vCon:
Bob: "Hi, I'd like to request a refund for order #12345"
Alice: "I'd be happy to help you with that refund request."
```

**4. Add analysis:**

```
Add sentiment analysis showing positive sentiment (0.8 score) 
from "SentimentAI" vendor
```

Congratulations! You've created a complete vCon with dialog and analysis.

***

## Core Operations

### Creating vCons

#### Basic Creation

```
Create a vCon with subject "Team Meeting" and party "John Doe" 
with email john@example.com
```

#### Using Templates

```
Create a phone_call vCon between two people discussing product pricing
```

Available templates:

* `phone_call` - Two-party phone conversation
* `chat_conversation` - Multi-party text chat
* `email_thread` - Email conversation
* `video_meeting` - Video conference call
* `custom` - Start from scratch

#### With Multiple Parties

```
Create a vCon for a sales call with:
- Sales rep: Alice (alice@company.com)
- Customer: Bob (bob@customer.com)
- Manager: Carol (carol@company.com)
Subject: "Q4 Contract Negotiation"
```

***

### Reading vCons

#### Get by UUID

```
Get the vCon with UUID abc-123-def-456
```

#### Get Recent vCons

```
Show me the 10 most recent vCons
```

Or use the `vcon://v1/vcons/recent` resource:

```
Read the vcon://v1/vcons/recent resource
```

#### Get Specific Fields

```
Show me just the parties from vCon abc-123
```

Use resources:

* `vcon://v1/vcons/{uuid}/parties` - Just parties
* `vcon://v1/vcons/{uuid}/dialog` - Just dialog
* `vcon://v1/vcons/{uuid}/analysis` - Just analysis
* `vcon://v1/vcons/{uuid}/attachments` - Just attachments
* `vcon://v1/vcons/{uuid}/metadata` - Just metadata
* `vcon://v1/vcons/{uuid}/transcript` - Transcript analysis (derived)
* `vcon://v1/vcons/{uuid}/summary` - Summary analysis (derived)
* `vcon://v1/vcons/{uuid}/tags` - Tags as object (derived)

***

### Searching vCons

#### Basic Search (Filtering)

Search by subject, party name, or date:

```
Find vCons from last week about billing
```

```
Find vCons where John Smith was a participant
```

```
Search for vCons created between Jan 1 and Jan 31 with subject "support"
```

#### Keyword Search

Full-text search across dialog and analysis:

```
Search for conversations mentioning "refund" or "return"
```

```
Find vCons where someone said "technical issue"
```

#### Semantic Search

AI-powered search by meaning (requires embeddings):

```
Find conversations where customers were frustrated with delivery
```

```
Search for discussions about product features
```

#### Hybrid Search

Combines keyword and semantic for best results:

```
Search for billing disputes using both exact matches and similar concepts
```

***

### Adding Content

#### Add Dialog

Add conversation segments:

```
Add a recording dialog to vCon abc-123:
- Type: recording
- Start time: 2025-01-15T10:00:00Z
- Duration: 300 seconds
- URL: https://storage.example.com/call123.mp3
```

```
Add a text message:
"Hi, thanks for calling support!"
From party 0 at 10:00 AM
```

#### Add Analysis

Add AI/ML analysis results:

```
Add transcript analysis to vCon abc-123:
- Type: transcript
- Vendor: OpenAI
- Product: Whisper-1
- Body: "Full transcript text here..."
- Dialog: 0 (references first dialog)
```

```
Add sentiment analysis showing negative sentiment (-0.6)
from vendor "SentimentAnalyzer"
```

#### Add Attachments

Attach related files:

```
Add an attachment to vCon abc-123:
- Type: application/pdf
- Party: 1
- Body: base64-encoded PDF content
```

***

### Updating vCons

Update top-level vCon metadata:

```
Update vCon abc-123 with subject "Updated Subject Line"
```

```
Add a "priority" extension with value "high" to vCon abc-123
```

**Note:** To modify parties, dialog, or analysis, add new items. The vCon spec favors immutability.

***

### Tagging & Organization

#### Add Tags

```
Tag vCon abc-123 as:
- department: support
- priority: high
- customer_id: CUST-789
```

#### Search by Tags

```
Find all vCons tagged as department:sales and priority:high
```

```
Show me high priority support tickets from this week
```

#### View All Tags

```
Show me all unique tags in the database
```

#### Remove Tags

```
Remove the priority tag from vCon abc-123
```

See [Tag Management Guide](/guide/tags) for complete tag documentation.

***

### Deleting vCons

```
Delete vCon abc-123
```

**Warning:** This permanently deletes the vCon and all related data (parties, dialog, analysis, attachments). This action cannot be undone.

***

## Common Workflows

### Workflow 1: Customer Support Call

**Step 1: Create vCon**

```
Create a support call vCon between agent Sarah and customer Mike
about a billing issue
```

**Step 2: Add Recording**

```
Add a recording dialog:
- URL: https://recordings.example.com/call-456.mp3
- Duration: 420 seconds
- Start time: now
```

**Step 3: Add Transcript**

```
Add transcript analysis from OpenAI Whisper showing the conversation...
```

**Step 4: Add Sentiment**

```
Add sentiment analysis showing the customer was initially frustrated (-0.4)
but ended satisfied (0.7)
```

**Step 5: Tag for Organization**

```
Tag this vCon:
- department: support
- issue_type: billing
- resolution: resolved
- customer_satisfaction: high
```

**Step 6: Search Later**

```
Find all resolved billing issues from this month where
customer satisfaction was high
```

***

### Workflow 2: Sales Call Analysis

**Step 1: Create from Template**

```
Create a phone_call vCon for a sales discovery call with
prospect Jane at Acme Corp
```

**Step 2: Add Transcript**

```
Add the call transcript as analysis...
```

**Step 3: Extract Action Items**

```
Add analysis of type "action_items" with extracted next steps
```

**Step 4: Generate Summary**

```
Add a summary analysis highlighting key discussion points
and customer pain points
```

**Step 5: Tag**

```
Tag as:
- sales_stage: discovery
- industry: enterprise_software
- deal_size: 50k
- next_action: demo_scheduled
```

***

### Workflow 3: Research Dataset

**Step 1: Batch Create vCons**

```
Create 5 vCons for research interviews about user experience
```

**Step 2: Add Interview Transcripts**

```
For each vCon, add the transcript as a text dialog
```

**Step 3: Add Analysis**

```
Add theme analysis identifying common patterns
```

**Step 4: Search Across Dataset**

```
Search all research vCons for mentions of "usability issues"
```

**Step 5: Export Findings**

```
Get all vCons tagged as research:ux_study and show
their analysis results
```

***

## Using with Claude Desktop

### Example Conversations

#### Natural Language Commands

Claude understands natural language - you don't need precise syntax:

```
❌ create_vcon(subject="test", parties=[...])

✅ Create a vCon for a team meeting
✅ Make a new vCon about product development
✅ Set up a vCon for yesterday's client call
```

#### Complex Queries

```
Find all customer support vCons from last quarter where
the sentiment was negative and the issue was about billing,
then show me the most common complaints
```

Claude will:

1. Search vCons by date range
2. Filter for support + billing tags
3. Filter for negative sentiment
4. Analyze common themes
5. Present findings

#### Multi-Step Operations

```
Create a vCon for a sales call, add the transcript from
the file I shared, analyze the sentiment, extract action items,
and tag it appropriately
```

Claude can chain multiple tool calls automatically.

***

## Tips & Best Practices

### Creating vCons

✅ **DO:**

* Use descriptive subjects
* Add all parties involved
* Include timestamps when known
* Use templates for common scenarios

❌ **DON'T:**

* Create duplicate vCons
* Leave subject empty unless truly unknown
* Forget to specify party roles

### Adding Content

✅ **DO:**

* Reference dialog indexes in analysis
* Include vendor info for all analysis
* Use appropriate encoding (none/json/base64url)
* Add timestamps to dialog

❌ **DON'T:**

* Store large files directly (use URLs instead)
* Mix encoding types inconsistently
* Forget to specify analysis type

### Searching

✅ **DO:**

* Use semantic search for conceptual queries
* Use keyword search for exact terms
* Use hybrid search when uncertain
* Add tags for better organization

❌ **DON'T:**

* Search by vCon content without indexes
* Expect instant results with semantic search (requires embeddings)
* Over-complicate search queries

### Tagging

✅ **DO:**

* Use consistent tag naming (e.g., `department:sales`)
* Tag early and often
* Use hierarchical tags (e.g., `issue:billing:refund`)
* Document your tag schema

❌ **DON'T:**

* Create one-off tag names
* Use spaces in tag keys
* Forget to remove outdated tags

***

## Understanding Resources

Resources provide read-only access to vCon data:

### List Resources

```
What vCon resources are available?
```

### Common Resources

| Resource                             | Purpose                  | Example                     |
| ------------------------------------ | ------------------------ | --------------------------- |
| `vcon://v1/vcons/recent`             | 10 most recent vCons     | Full vCon objects           |
| `vcon://v1/vcons/recent/25`          | Recent with custom limit | Max 100                     |
| `vcon://v1/vcons/{uuid}`             | Specific vCon            | Complete vCon               |
| `vcon://v1/vcons/{uuid}/metadata`    | Just metadata            | Without dialog/analysis     |
| `vcon://v1/vcons/{uuid}/parties`     | Just parties             | Array of parties            |
| `vcon://v1/vcons/{uuid}/dialog`      | All dialog               | Array of dialog objects     |
| `vcon://v1/vcons/{uuid}/analysis`    | All analysis             | Array of analysis objects   |
| `vcon://v1/vcons/{uuid}/attachments` | All attachments          | Array of attachment objects |
| `vcon://v1/vcons/{uuid}/transcript`  | Transcript analysis      | Filtered analysis array     |
| `vcon://v1/vcons/{uuid}/summary`     | Summary analysis         | Filtered analysis array     |
| `vcon://v1/vcons/{uuid}/tags`        | Tags                     | Parsed tags object          |

### Using Resources

```
Read vcon://v1/vcons/recent
```

```
Read vcon://v1/vcons/abc-123-def/parties
```

Resources are faster than tools for simple reads.

***

## Understanding Prompts

Prompts guide Claude in using the right search strategy:

### Available Prompts

1. **find\_by\_exact\_tags** - Precise tag matches
2. **find\_by\_semantic\_search** - Meaning-based search
3. **find\_by\_keywords** - Text search
4. **find\_recent\_by\_topic** - Recent vCons on topic
5. **find\_by\_party** - Party-specific vCons
6. **discover\_available\_tags** - Explore tag schema
7. **complex\_search** - Multi-criteria queries
8. **find\_similar\_conversations** - Similar to example
9. **help\_me\_search** - Search strategy help

### Using Prompts

Claude automatically selects the right prompt, but you can request:

```
Use exact tag matching to find high-priority sales calls
```

```
Help me search for what I'm looking for
```

See [Prompts Guide](/guide/prompts) for detailed documentation.

***

## Error Handling

### Common Errors

#### "vCon not found"

```
❌ Get vCon abc-123
   Error: vCon with UUID abc-123 not found
```

**Solution:** Check the UUID is correct:

```
✅ Show me recent vCons to find the correct UUID
```

#### "Invalid vCon data"

```
❌ Create vCon without parties
   Error: vCon must have at least one party
```

**Solution:** Include required fields:

```
✅ Create vCon with subject "Meeting" and party "Alice"
```

#### "Search returned no results"

```
❌ Find vCons about "xyz" from 2020
   No results found
```

**Solution:** Broaden search criteria:

```
✅ Show me all vCons from 2020 first
```

***

## Performance Tips

### For Large Datasets

1. **Use tags** for filtering before search
2. **Use date ranges** to limit scope
3. **Use resources** for simple reads
4. **Index dialog content** for keyword search
5. **Generate embeddings** for semantic search

### For Fast Queries

1. **Query by UUID** when known (fastest)
2. **Use resources** instead of tools for reads
3. **Limit results** to what you need
4. **Cache frequently accessed vCons**

***

## Database Tools

The server includes database inspection tools:

### View Database Structure

```
Show me the database structure
```

Uses `get_database_shape` tool.

### View Performance Stats

```
What are the database performance stats?
```

Uses `get_database_stats` tool.

### Analyze Query Performance

```
Analyze this query: SELECT * FROM vcons WHERE subject LIKE '%test%'
```

Uses `analyze_query` tool.

See [Database Tools Guide](/guide/database-tools) for details.

***

## Next Steps

### Learn More

* [**Search Guide**](/guide/search) - Master all search capabilities
* [**Tag Management**](/guide/tags) - Organize with tags
* [**Prompts Guide**](/guide/prompts) - Understand prompts
* [**API Reference**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/api/README.md) - Complete tool documentation

### Advanced Usage

* [**Plugin Development**](/development/plugins) - Extend functionality
* [**Custom Tools**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/development/custom-tools.md) - Add your own tools
* [**Embeddings & Search**](/development/embeddings) - Set up semantic search

### Examples

* [**Code Examples**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/README.md) - Real-world examples
* [**Integration Patterns**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/README.md) - Integration guides

***

## Getting Help

### Quick Help in Claude

```
How do I create a vCon?
```

```
What search tools are available?
```

```
Help me search for frustrated customers
```

### Documentation

* [**Installation Guide**](/guide/installation) - Setup troubleshooting
* [**API Reference**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/api/README.md) - Tool parameters
* [**Reference Docs**](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/reference/README.md) - Technical specifications

### Community

* **GitHub Issues** - Bug reports
* **GitHub Discussions** - Questions and ideas
* **Discord** - Real-time chat (coming soon)

***

## Quick Reference

### Most Common Commands

| Task         | Example                                   |
| ------------ | ----------------------------------------- |
| Create vCon  | `Create a vCon for a support call`        |
| Get vCon     | `Show me vCon abc-123`                    |
| Search       | `Find vCons about billing from last week` |
| Add dialog   | `Add a text dialog saying "Hello"`        |
| Add analysis | `Add sentiment analysis from OpenAI`      |
| Tag          | `Tag this vCon as priority:high`          |
| Delete       | `Delete vCon abc-123`                     |

### Key Concepts

* **vCon** - Container for conversation data
* **Party** - Participant in conversation
* **Dialog** - Conversation segment (recording, text, etc.)
* **Analysis** - AI/ML results (transcript, sentiment, etc.)
* **Attachment** - Related files
* **Tags** - Metadata for organization
* **Resources** - Read-only data access
* **Prompts** - Search strategy guidance

***

**Ready to dive deeper?** Continue to [Search Guide](/guide/search) →


# Search & Query

## Overview

The vCon MCP server now exposes a recommended unified search surface plus the older specialized search tools.

For new clients, prefer `vcon_search` first. It gives you one predictable response envelope, explicit `include` groups, cursor pagination, and response-size budgeting. The older search tools are still available and still useful for compatibility or specialized flows.

## Recommended Starting Point

### `vcon_search` - Unified Search

**Best for:** New clients that want one search entry point with predictable parsing

**Modes:**

* `metadata`
* `keyword`
* `semantic`
* `hybrid`

**Key advantages:**

* Stable `{ok, items, page}` envelope
* Explicit `include` groups such as `core`, `summary`, `tags`, and `dealer`
* Cursor pagination instead of mixed ad hoc paging behavior
* Explicit `max_response_bytes` so oversized responses fail loudly with `RESPONSE_TOO_LARGE`

**Example:**

```json
{
  "mode": "keyword",
  "query": "billing dispute",
  "filters": {
    "tags": {
      "portal": "negative_experience"
    }
  },
  "include": ["core", "summary", "dealer", "tags"],
  "limit": 25,
  "max_response_bytes": 120000
}
```

**Typical companion tools:**

* `vcon_capabilities` to discover supported modes, includes, and byte budgets
* `vcon_taxonomy` to discover the portal taxonomy and preferred dealer source
* `vcon_fetch` to expand a selected result with additional include groups

## Legacy Search Tools

The tools below remain supported and useful. They are especially helpful for older clients, direct low-level access, or cases where you intentionally want their narrower behavior.

## Available Search Tools

### 1. `search_vcons` - Basic Filter Search

**Best for:** Finding vCons by metadata (subject, parties, dates)

**Searches:**

* Subject line
* Party names, emails, phone numbers
* Creation dates

**Does NOT search:**

* Dialog content
* Analysis content
* Attachments

**Example:**

```json
{
  "subject": "customer support",
  "party_name": "John Doe",
  "start_date": "2024-01-01T00:00:00Z",
  "limit": 10
}
```

**Returns:** Complete vCon objects matching the filters

***

### 2. `search_vcons_content` - Keyword Search

**Best for:** Finding specific words or phrases in conversation content

**Searches:**

* ✅ Subject
* ✅ Dialog bodies (conversations, transcripts)
* ✅ Analysis bodies (summaries, sentiment, etc.)
* ✅ Party information (names, emails, phones)
* ❌ Attachments (not indexed for full-text search)

**Features:**

* Full-text search with ranking
* Typo tolerance via trigram indexing
* Highlighted snippets in results
* Tag filtering support
* Date range filtering

**Example:**

```json
{
  "query": "billing issue refund",
  "tags": {"department": "sales"},
  "start_date": "2024-01-01T00:00:00Z",
  "limit": 50
}
```

**Returns:** Ranked results with snippets showing where matches were found

**Result format:**

```json
{
  "success": true,
  "count": 5,
  "results": [
    {
      "vcon_id": "uuid",
      "content_type": "analysis",  // or "subject", "dialog", "party"
      "content_index": 0,
      "relevance_score": 0.85,
      "snippet": "...regarding the billing issue and potential refund..."
    }
  ]
}
```

***

### 3. `search_vcons_semantic` - AI-Powered Semantic Search

**Best for:** Finding conversations by meaning, not just keywords

**Searches:**

* ✅ Subject (embedded)
* ✅ Dialog bodies (embedded)
* ✅ Analysis bodies with `encoding='none'` or `NULL` (embedded)
* ❌ Analysis with `encoding='base64url'` or `encoding='json'` (not embedded)
* ❌ Attachments (not embedded)

**Features:**

* Finds conceptually similar content
* Works across paraphrases and synonyms
* AI embeddings using 384-dimensional vectors
* Tag filtering support
* Similarity threshold control

**Requirements:**

* Embeddings must be generated first (see embedding documentation)
* Currently requires pre-computed embedding vector (384 dimensions)

**Example:**

```json
{
  "query": "customer angry about late delivery",
  "threshold": 0.7,
  "limit": 20
}
```

**Returns:** Similar conversations ranked by semantic similarity

***

### 4. `search_vcons_hybrid` - Combined Keyword + Semantic Search

**Best for:** Comprehensive search combining exact matches and conceptual similarity

**Searches:**

* Everything from keyword search (subject, dialog, analysis, parties)
* Everything from semantic search (embedded content)

**Features:**

* Combines full-text and semantic search
* Adjustable weighting between keyword and semantic results
* Best of both worlds: exact matches + conceptual matches
* Tag filtering support

**Example:**

```json
{
  "query": "billing dispute",
  "semantic_weight": 0.6,
  "tags": {"priority": "high"},
  "limit": 30
}
```

**Parameters:**

* `semantic_weight`: 0-1 (default 0.6)
  * 0.0 = 100% keyword search
  * 1.0 = 100% semantic search
  * 0.6 = 60% semantic, 40% keyword (recommended)

**Returns:** Combined results with both keyword and semantic scores

***

## What About Attachments?

### Current Status

**Attachments are NOT indexed for search** in the current implementation.

**Why?**

1. **Binary content**: Many attachments contain binary data (PDFs, images, audio) that isn't suitable for text-based search
2. **Encoding**: Attachments with `encoding='base64url'` contain encoded data, not searchable text
3. **Structured data**: Attachments with `encoding='json'` contain structured data that produces poor quality embeddings

### Special Case: Tags

Attachments of type `tags` with `encoding='json'` ARE used for filtering, but not for content search.

Example tags attachment:

```json
{
  "type": "tags",
  "encoding": "json",
  "body": ["department:sales", "priority:high", "region:west"]
}
```

These tags can be used with the `tags` parameter in any search tool:

```json
{
  "query": "customer complaint",
  "tags": {"department": "sales", "priority": "high"}
}
```

### Future Enhancements

Potential future support for attachment content search:

1. **Text extraction**: Extract text from PDFs, Word docs, etc.
2. **Audio transcription**: Transcribe audio attachments to searchable text
3. **OCR**: Extract text from images
4. **Selective indexing**: Index only attachments with text content

If you need to search attachment content, consider:

1. Extracting text and adding it as an analysis element
2. Adding a summary of attachment content as an analysis
3. Using attachment metadata in tags

***

## Analysis Encoding and Search

### Analysis Elements ARE Searchable

Analysis elements are included in search, with filtering based on encoding:

| Encoding         | Keyword Search | Semantic Search | Notes                                |
| ---------------- | -------------- | --------------- | ------------------------------------ |
| `none` or `NULL` | ✅ Yes          | ✅ Yes           | Plain text content, ideal for search |
| `json`           | ✅ Yes          | ❌ No            | Included in keyword search only      |
| `base64url`      | ✅ Yes          | ❌ No            | Included in keyword search only      |

### Why Filter Semantic Search by Encoding?

Analysis with `encoding='none'` contains human-readable text like:

* Conversation summaries
* Transcriptions
* Sentiment analysis results
* Translation output
* Natural language insights

These are ideal for semantic search because they contain meaningful natural language.

Analysis with `encoding='json'` or `encoding='base64url'` typically contains:

* Structured data (poor quality embeddings)
* Binary content (not suitable for embeddings)
* Encoded data (not searchable as text)

***

## Search Comparison

| Feature             | vcon\_search                                          | search\_vcons | search\_vcons\_content | search\_vcons\_semantic | search\_vcons\_hybrid |
| ------------------- | ----------------------------------------------------- | ------------- | ---------------------- | ----------------------- | --------------------- |
| Subject             | ✅ Depends on mode                                     | ✅ Filter      | ✅ Search               | ✅ Search                | ✅ Search              |
| Dialog              | ✅ Depends on mode/include                             | ❌             | ✅ Search               | ✅ Search                | ✅ Search              |
| Analysis            | ✅ Depends on mode/include                             | ❌             | ✅ Search               | ✅ (encoding=none)       | ✅ All                 |
| Attachments         | ✅ Via explicit include groups on fetch/search results | ❌             | ❌                      | ❌                       | ❌                     |
| Party Info          | ✅ Depends on mode/include                             | ✅ Filter      | ✅ Search               | ❌                       | ✅ Search              |
| Tags                | ✅ Filter and return                                   | ❌             | ✅ Filter               | ✅ Filter                | ✅ Filter              |
| Ranking             | ✅ Depends on mode                                     | ❌             | ✅ Relevance            | ✅ Similarity            | ✅ Combined            |
| Snippets            | ❌                                                     | ❌             | ✅ Yes                  | ❌                       | ❌                     |
| Requires Embeddings | Only for semantic/hybrid mode                         | ❌             | ❌                      | ✅                       | ⚠️ Optional           |
| Cursor Pagination   | ✅ Yes                                                 | ❌             | ❌                      | ❌                       | ❌                     |
| Response Budgeting  | ✅ `max_response_bytes`                                | ❌             | ❌                      | ❌                       | ❌                     |

***

## Best Practices

### When to Use Each Tool

1. **`vcon_search`**: Default choice for new clients
   * "Use one parser for metadata, keyword, semantic, and hybrid search"
   * "Return lightweight summaries plus dealer info"
   * "Fail loudly instead of silently returning oversized payloads"
2. **`search_vcons`**: Quick metadata lookups in older clients
   * "Find vCons with party email <john@example.com>"
   * "Show me vCons from last week"
   * "List vCons with subject containing 'urgent'"
3. **`search_vcons_content`**: Keyword-based content search
   * "Find conversations mentioning 'refund'"
   * "Search for 'technical support' in dialog"
   * "Find analysis containing 'positive sentiment'"
4. **`search_vcons_semantic`**: Concept-based search
   * "Find conversations where customer was unhappy"
   * "Show me calls about payment issues"
   * "Find similar conversations to this one"
5. **`search_vcons_hybrid`**: Comprehensive search
   * "Find all billing-related conversations" (gets both exact matches and related topics)
   * "Search for customer complaints" (finds variations and synonyms)
   * Best when you want both precision and recall

### Performance Tips

1. **Use filters**: Date ranges and tags can dramatically reduce search scope
2. **Set appropriate limits**: Start with smaller limits (10-20) for faster results
3. **Choose the right tool**: Don't use semantic search if keyword search is sufficient
4. **Pre-generate embeddings**: Semantic search requires embeddings to be generated beforehand

***

## Generating Embeddings

For semantic and hybrid search to work effectively, you need to generate embeddings for your vCons.

See the following guides:

* [INGEST\_AND\_EMBEDDINGS.md](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/INGEST_AND_EMBEDDINGS.md) - Complete guide to embedding generation
* [EMBEDDING\_STRATEGY\_UPGRADE.md](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/EMBEDDING_STRATEGY_UPGRADE.md) - Details on which content is embedded

**Quick start:**

```bash
# Generate embeddings continuously
npm run sync:embeddings

# Or as part of full sync
npm run sync

# Check embedding coverage
npm run embeddings:check
```

***

## Troubleshooting

### "No results found" for content search

* Check that the content exists in dialog or analysis
* Try a simpler query (fewer words)
* Use wildcards or partial words
* Check date range filters

### "Embedding generation not yet implemented"

* Semantic search currently requires pre-computed embeddings
* Use `search_vcons_content` for keyword search instead
* Generate embeddings using the scripts in `/scripts/`

### "Embedding must be 384 dimensions"

* The system uses 384-dimensional embeddings
* If you're providing embeddings, ensure they match this dimension
* Use `text-embedding-3-small` with `dimensions=384` (OpenAI)
* Or use `sentence-transformers/all-MiniLM-L6-v2` (Hugging Face)

### Poor search results

* For keyword search: Try simpler, more specific terms
* For semantic search: Ensure embeddings are up to date
* For hybrid search: Adjust `semantic_weight` parameter
* Consider using tags to filter results

***

## Examples

### Find customer complaints in dialog

```json
{
  "query": "customer complaint angry upset frustrated",
  "limit": 20
}
```

### Find high-priority sales conversations

```json
{
  "query": "pricing quote proposal",
  "tags": {
    "department": "sales",
    "priority": "high"
  },
  "start_date": "2024-01-01T00:00:00Z"
}
```

### Hybrid search with keyword emphasis

```json
{
  "query": "billing invoice payment",
  "semantic_weight": 0.3,
  "limit": 30
}
```

### Find conversations similar to a specific vCon

1. Get the vCon's embedding from the database
2. Use it in semantic search:

```json
{
  "embedding": [0.123, 0.456, ...],  // 384 dimensions
  "threshold": 0.75,
  "limit": 10
}
```

***

## Related Documentation

* [Getting Started](/guide/getting-started) - Getting started with vCon MCP
* [Ingest and Embeddings](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/INGEST_AND_EMBEDDINGS.md) - Embedding generation
* [Search Optimization Guide](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/SEARCH_OPTIMIZATION_GUIDE.md) - Database search performance


# Tag Management

## Overview

Tags in vCon are key-value pairs that provide simple, flexible metadata for categorization, filtering, and organization. Tags are stored as a special attachment with `type: "tags"`, `encoding: "json"`, and a body containing an array of `"key:value"` strings.

## Storage Format

Tags are stored internally as an attachment in the vCon:

```json
{
  "type": "tags",
  "encoding": "json",
  "body": "[\"department:sales\", \"priority:high\", \"status:open\"]"
}
```

This format is automatically managed by the tag tools - you don't need to interact with attachments directly.

## Available Tools

### 1. `manage_tag` - Add, Update, or Remove a Single Tag

Manage a single tag on a vCon. Use action `"set"` to add or update, `"remove"` to delete.

**Input:**

```typescript
{
  vcon_uuid: string;      // UUID of the vCon (required)
  action: "set" | "remove";  // Action to perform (required)
  key: string;            // Tag key/name (required)
  value?: string | number | boolean;  // Tag value (required when action is "set")
}
```

**Examples:**

```javascript
// Add a string tag
manage_tag({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000",
  action: "set",
  key: "department",
  value: "sales"
})

// Add a number tag
manage_tag({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000",
  action: "set",
  key: "priority",
  value: 5
})

// Add a boolean tag
manage_tag({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000",
  action: "set",
  key: "resolved",
  value: true
})

// Remove a tag
manage_tag({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000",
  action: "remove",
  key: "priority"
})
```

***

### 2. `get_tags` - Get One or All Tags

Retrieve tags from a vCon. Provide a `key` to get one tag value, or omit `key` to get all tags.

**Input:**

```typescript
{
  vcon_uuid: string;      // UUID of the vCon (required)
  key?: string;           // Specific tag key to retrieve (omit for all tags)
  default_value?: string | number | boolean | null;  // Fallback if key not found (default: null)
}
```

**Examples:**

```javascript
// Get a specific tag
get_tags({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000",
  key: "department"
})

// Get a tag with fallback
get_tags({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000",
  key: "priority",
  default_value: "normal"
})

// Get all tags
get_tags({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000"
})
```

***

### 3. `remove_all_tags` - Remove All Tags

Remove all tags from a vCon.

**Input:**

```typescript
{
  vcon_uuid: string;      // UUID of the vCon
}
```

**Example:**

```javascript
remove_all_tags({
  vcon_uuid: "123e4567-e89b-12d3-a456-426614174000"
})
```

**Response:**

```json
{
  "success": true,
  "message": "All tags removed from vCon 123e4567-e89b-12d3-a456-426614174000"
}
```

***

### 7. `search_by_tags` - Search vCons by Tags

Search for vCons that have specific tag values. All specified tags must match (AND logic).

**Input:**

```typescript
{
  tags: {                 // Tag key-value pairs to search for
    [key: string]: string;
  };
  limit?: number;         // Maximum UUIDs to return (default: 50, max: 100)
  return_full_vcons?: boolean;  // Return full vCon objects (default: auto based on result size)
  max_full_vcons?: number;      // Max full vCon objects to return (default: 20)
}
```

**Behavior:**

* Always returns `vcon_uuids` for all matching vCons (up to `limit`)
* For small result sets (≤20), full vCon objects are returned by default
* For large result sets (>20), only UUIDs are returned by default to prevent response size limits
* Use `get_vcon` to fetch individual vCons by UUID when needed

**Examples:**

```javascript
// Find all sales department vCons (returns UUIDs for large sets)
search_by_tags({
  tags: {
    department: "sales"
  }
})

// Find high-priority open sales calls (small set, returns full vCons)
search_by_tags({
  tags: {
    department: "sales",
    priority: "high",
    status: "open"
  },
  limit: 10
})

// Explicitly request full vCons for large result set (limited to 20)
search_by_tags({
  tags: {
    direction: "out",
    engagement: "true"
  },
  limit: 100,
  return_full_vcons: true,
  max_full_vcons: 20
})
```

**Response:**

```json
{
  "success": true,
  "count": 2,
  "tags_searched": {
    "department": "sales",
    "priority": "high"
  },
  "vcon_uuids": [
    "123e4567-e89b-12d3-a456-426614174000",
    "987fcdeb-51a2-43f1-b9c6-d8e7f6a5b4c3"
  ],
  "vcons": [
    { /* full vCon object */ },
    { /* full vCon object */ }
  ]
}
```

***

### 8. `get_unique_tags` - Get All Unique Tags

Get a list of all unique tag keys and their possible values across all vCons. This is useful for:

* Discovering what tags are in use
* Building tag selection UIs
* Analytics and reporting
* Understanding your tag taxonomy

**Input:**

```typescript
{
  include_counts?: boolean;  // Include usage counts (default: false)
  key_filter?: string;       // Filter by key substring (case-insensitive)
  min_count?: number;        // Minimum occurrence count (default: 1)
}
```

**Examples:**

```javascript
// Get all unique tags
get_unique_tags({})

// Get all unique tags with usage counts
get_unique_tags({
  include_counts: true
})

// Get only department-related tags
get_unique_tags({
  key_filter: "department",
  include_counts: true
})

// Get tags that appear at least 5 times
get_unique_tags({
  include_counts: true,
  min_count: 5
})
```

**Response (without counts):**

```json
{
  "success": true,
  "unique_keys": [
    "campaign",
    "department",
    "priority",
    "region",
    "status"
  ],
  "unique_key_count": 5,
  "tags_by_key": {
    "campaign": ["spring_2024", "summer_2024", "fall_2024"],
    "department": ["engineering", "sales", "support"],
    "priority": ["high", "low", "medium"],
    "region": ["east", "north", "south", "west"],
    "status": ["closed", "open", "pending"]
  },
  "total_vcons_with_tags": 150,
  "summary": {
    "total_unique_keys": 5,
    "total_vcons": 150,
    "filter_applied": false,
    "min_count_filter": 1
  }
}
```

**Response (with counts):**

```json
{
  "success": true,
  "unique_keys": ["department", "priority", "status"],
  "unique_key_count": 3,
  "tags_by_key": {
    "department": ["engineering", "sales", "support"],
    "priority": ["high", "low", "medium"],
    "status": ["closed", "open"]
  },
  "counts_per_value": {
    "department": {
      "sales": 45,
      "support": 38,
      "engineering": 22
    },
    "priority": {
      "high": 30,
      "medium": 50,
      "low": 25
    },
    "status": {
      "open": 60,
      "closed": 45
    }
  },
  "total_vcons_with_tags": 150,
  "summary": {
    "total_unique_keys": 3,
    "total_vcons": 150,
    "filter_applied": false,
    "min_count_filter": 1
  }
}
```

**Use Cases:**

* **UI Building**: Populate dropdown menus with available tag values
* **Analytics**: Understand tag distribution and usage patterns
* **Data Quality**: Find tags that are rarely used or might be misspelled
* **Tag Cleanup**: Identify tags that should be standardized or removed

***

## Integration with Search Tools

Tags can also be used to filter results in the main search tools:

### Keyword Search with Tags

```javascript
search_vcons_content({
  query: "customer complaint",
  tags: {
    department: "support",
    priority: "high"
  }
})
```

### Semantic Search with Tags

```javascript
search_vcons_semantic({
  query: "billing issues",
  tags: {
    department: "billing",
    status: "open"
  }
})
```

### Hybrid Search with Tags

```javascript
search_vcons_hybrid({
  query: "refund request",
  tags: {
    department: "sales",
    region: "west"
  }
})
```

***

## Tag Discovery and Analytics

### Get All Tags in Your System

```javascript
// Discover all tags
const result = get_unique_tags({ include_counts: true })

// Result shows:
// - All tag keys in use
// - All possible values for each key
// - How many vCons have each value
// - Total vCons with tags
```

### Build Tag Selection UI

```javascript
// Get available department values
const tags = get_unique_tags({
  key_filter: "department"
})

// Use tags.tags_by_key.department to populate dropdown:
// ["sales", "support", "engineering"]
```

### Find Rarely Used Tags

```javascript
// Get tags that appear at least 10 times
const commonTags = get_unique_tags({
  include_counts: true,
  min_count: 10
})

// Tags not in this result appear < 10 times
// Consider standardizing or removing them
```

### Analyze Tag Distribution

```javascript
const analysis = get_unique_tags({
  include_counts: true
})

// Analysis shows:
// - Which departments handle the most conversations
// - Priority distribution across your organization
// - Status breakdown
```

***

## Common Use Cases

### 1. Customer Tracking

```javascript
// Tag a vCon with customer information
manage_tag({
  vcon_uuid: vcon_uuid,
  action: "set",
  key: "customer_id",
  value: "CUST-12345"
})

manage_tag({
  vcon_uuid: vcon_uuid,
  action: "set",
  key: "customer_name",
  value: "Acme Corp"
})

// Find all conversations with a specific customer
search_by_tags({
  tags: { customer_id: "CUST-12345" }
})
```

### 2. Department Organization

```javascript
// Tag conversations by department
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "department", value: "sales" })
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "team", value: "enterprise" })
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "region", value: "west" })

// Find all sales conversations
search_by_tags({
  tags: { department: "sales" }
})
```

### 3. Status Tracking

```javascript
// Set initial status
manage_tag({
  vcon_uuid: vcon_uuid,
  action: "set",
  key: "status",
  value: "open"
})

// Update when resolved
manage_tag({
  vcon_uuid: vcon_uuid,
  action: "set",
  key: "status",
  value: "resolved"
})

manage_tag({
  vcon_uuid: vcon_uuid,
  action: "set",
  key: "resolved_at",
  value: new Date().toISOString()
})

// Find all open issues
search_by_tags({
  tags: { status: "open" }
})
```

### 4. Priority Management

```javascript
// Set priority level
manage_tag({
  vcon_uuid: vcon_uuid,
  action: "set",
  key: "priority",
  value: "high"
})

// Find high priority items
search_by_tags({
  tags: { priority: "high" }
})
```

### 5. Campaign Tracking

```javascript
// Tag conversations from a campaign
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "campaign", value: "spring_2024" })
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "source", value: "web_chat" })
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "promotion", value: "free_trial" })

// Analyze campaign performance
search_by_tags({
  tags: { campaign: "spring_2024" }
})
```

***

## Best Practices

### Tag Naming

* Use lowercase with underscores: `customer_id`, `created_date`
* Be consistent across your application
* Avoid spaces in tag keys
* Use descriptive names: `priority` instead of `p`

### Tag Values

* Keep values simple and consistent
* Use a predefined set of values for categorical tags (e.g., status: "open", "closed", "pending")
* For dates, use ISO 8601 format: "2025-10-14T10:30:00Z"
* For booleans, use "true" or "false" strings

### Performance

* Use tags for filtering, not for storing large amounts of data
* Limit the number of tags per vCon to what's needed
* Tags are indexed for fast searching
* Consider using the materialized view for tag-heavy queries

### Organization

* Define a tagging schema for your application
* Document which tags are used and their possible values
* Use tags hierarchically: `department`, then `team`, then `region`

***

## Technical Details

### Storage

* Tags are stored as an attachment with `type: "tags"`
* The attachment has `encoding: "json"`
* The body contains a JSON array of "key:value" strings
* Example: `["department:sales", "priority:high"]`

### Querying

* Tags are indexed using a GIN index for fast containment queries
* A materialized view (`vcon_tags_mv`) provides optimized tag queries
* Search functions use JSONB containment operators (`@>`)

### Updates

* Adding/updating tags modifies the tags attachment
* If no tags attachment exists, one is created
* The vCon's `updated_at` timestamp is updated on tag changes
* Tags are atomic - you can't have partial updates

***

## Troubleshooting

### Tag not appearing after adding

* Check that the vCon UUID is correct
* Verify the tag was added successfully (check response)
* Use `get_tags` (without a key) to see all current tags

### Search returning unexpected results

* Remember that `search_by_tags` uses AND logic (all tags must match)
* Check that tag values match exactly (case-sensitive)
* Verify tags are strings in the search query

### Performance issues

* Consider refreshing the materialized view: `REFRESH MATERIALIZED VIEW vcon_tags_mv;`
* Check index usage with `EXPLAIN ANALYZE`
* Limit the number of tags per vCon

***

## Examples in Different Scenarios

### Phone Call Center

```javascript
// Tag incoming calls
manage_tag({ vcon_uuid: call_uuid, action: "set", key: "call_type", value: "inbound" })
manage_tag({ vcon_uuid: call_uuid, action: "set", key: "department", value: "support" })
manage_tag({ vcon_uuid: call_uuid, action: "set", key: "queue", value: "technical" })
manage_tag({ vcon_uuid: call_uuid, action: "set", key: "wait_time_seconds", value: "45" })
manage_tag({ vcon_uuid: call_uuid, action: "set", key: "handled_by", value: "agent_123" })
```

### Chat Support

```javascript
// Tag chat sessions
manage_tag({ vcon_uuid: chat_uuid, action: "set", key: "channel", value: "web_chat" })
manage_tag({ vcon_uuid: chat_uuid, action: "set", key: "topic", value: "billing" })
manage_tag({ vcon_uuid: chat_uuid, action: "set", key: "sentiment", value: "negative" })
manage_tag({ vcon_uuid: chat_uuid, action: "set", key: "escalated", value: "true" })
manage_tag({ vcon_uuid: chat_uuid, action: "set", key: "satisfaction_score", value: "2" })
```

### Email Threads

```javascript
// Tag email conversations
manage_tag({ vcon_uuid: email_uuid, action: "set", key: "thread_id", value: "THREAD-789" })
manage_tag({ vcon_uuid: email_uuid, action: "set", key: "category", value: "inquiry" })
manage_tag({ vcon_uuid: email_uuid, action: "set", key: "product", value: "enterprise_plan" })
manage_tag({ vcon_uuid: email_uuid, action: "set", key: "responded", value: "true" })
manage_tag({ vcon_uuid: email_uuid, action: "set", key: "response_time_hours", value: "2.5" })
```

***

## Migration from Other Systems

If you're migrating from systems that use different tag formats:

### From flat metadata

```javascript
// Old: { metadata: { dept: "sales", pri: 5 } }
// New:
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "department", value: "sales" })
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "priority", value: "5" })
```

### From nested structures

```javascript
// Old: { tags: { category: { primary: "support", secondary: "billing" } } }
// New: Flatten the structure
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "category_primary", value: "support" })
manage_tag({ vcon_uuid: vcon_uuid, action: "set", key: "category_secondary", value: "billing" })
```

***

## API Reference

For the complete API reference, see the tool definitions in `src/tools/tag-tools.ts`.

For database implementation details, see the query methods in `src/db/queries.ts`.


# Query Prompts

## Overview

Prompts are pre-built query templates that help you effectively search and retrieve vCons using the MCP server's search tools. They guide you on:

* **Exact match searches** using tags
* **Keyword searches** for specific phrases
* **Semantic searches** for natural language queries
* **Complex multi-criteria searches** combining multiple filters
* **Best practices** for different query scenarios

## Available Prompts

### 1. Find by Exact Tags

**Prompt:** `find_by_exact_tags`

**Use when:** You need precise category matching with specific tag values.

**Example queries:**

* "Find all customers from June that were tagged as 'angry'"
* "Show me high-priority sales calls"
* "List all support tickets marked as urgent"

**Arguments:**

* `tag_criteria` (required): Natural language description of tags to match
* `date_range` (optional): Date range description

**What it teaches:**

* How to parse natural language into specific tag key-value pairs
* Converting date descriptions to ISO 8601 format
* Using the `search_by_tags` tool effectively
* When to use `get_unique_tags` to discover available tags

***

### 2. Find by Semantic Search

**Prompt:** `find_by_semantic_search`

**Use when:** You want to find conversations by meaning, not just exact words.

**Example queries:**

* "Find all the angry customers from June"
* "Show me conversations about billing problems"
* "Locate positive customer feedback"

**Arguments:**

* `search_description` (required): Natural language description of what you're looking for
* `date_range` (optional): Date range description

**What it teaches:**

* How semantic search finds meaning beyond keywords
* Understanding similarity thresholds (0.6-0.8)
* Using the `search_vcons_semantic` tool
* When embeddings are required vs. keyword search

***

### 3. Find by Keywords

**Prompt:** `find_by_keywords`

**Use when:** You need to find specific words or phrases in conversation content.

**Example queries:**

* "Find conversations mentioning 'refund'"
* "Search for 'technical support' in dialogs"
* "Locate invoice #12345 discussions"

**Arguments:**

* `keywords` (required): Specific keywords or phrases to search
* `filters` (optional): Additional filters like dates, tags, parties

**What it teaches:**

* Full-text search capabilities
* What content is searchable (dialog, analysis, subject, parties)
* Using the `search_vcons_content` tool
* Interpreting relevance scores and snippets

***

### 4. Find Recent by Topic

**Prompt:** `find_recent_by_topic`

**Use when:** You need recent conversations filtered by topic or category.

**Example queries:**

* "Show me recent support calls"
* "Find this week's sales conversations"
* "List today's billing inquiries"

**Arguments:**

* `topic` (required): Topic or category to search
* `timeframe` (optional): Recency timeframe (default: last 30 days)

**What it teaches:**

* Converting relative time phrases to date ranges
* Choosing between tag-based and semantic search
* Combining date filters with topic searches
* Sorting and presenting time-sensitive results

***

### 5. Find by Party

**Prompt:** `find_by_party`

**Use when:** You need all conversations involving a specific person.

**Example queries:**

* "Find all conversations with <john@example.com>"
* "Show me calls from 555-1234"
* "List all interactions with Jane Smith"

**Arguments:**

* `party_identifier` (required): Name, email, or phone number
* `date_range` (optional): Date range to filter results

**What it teaches:**

* Identifying party type (email vs. phone vs. name)
* Using the appropriate party filter
* Using the `search_vcons` tool with party parameters
* Understanding case-insensitive and partial matching

***

### 6. Discover Available Tags

**Prompt:** `discover_available_tags`

**Use when:** You want to explore what tags exist in your system.

**Example queries:**

* "What tags are available for filtering?"
* "Show me all department tags"
* "List available priority levels"

**Arguments:**

* `tag_category` (optional): Focus on specific tag category

**What it teaches:**

* Using the `get_unique_tags` tool
* Understanding tag structure (key-value pairs)
* Viewing tag usage counts
* Building effective tag-based queries

***

### 7. Complex Multi-Criteria Search

**Prompt:** `complex_search`

**Use when:** You need to combine multiple search criteria.

**Example queries:**

* "Find high-priority sales calls from Q1 where customer mentioned pricing"
* "Show angry customers from the support department this month"
* "List urgent billing issues from last week"

**Arguments:**

* `search_criteria` (required): Complete search description with all criteria

**What it teaches:**

* Breaking down complex queries into components
* Choosing the right search strategy for mixed criteria
* Combining tags, keywords, dates, and semantic search
* Using the `search_vcons_hybrid` tool effectively

***

### 8. Find Similar Conversations

**Prompt:** `find_similar_conversations`

**Use when:** You want to find conversations similar to a specific one.

**Example queries:**

* "Find conversations similar to UUID abc-123-def"
* "Show me calls like this customer complaint"
* "Locate similar support tickets"

**Arguments:**

* `reference` (required): vCon UUID or topic description
* `limit` (optional): Number of similar conversations (default: 10)

**What it teaches:**

* Using vCon embeddings for similarity
* Adjusting similarity thresholds
* Understanding semantic similarity scores
* When to use UUID vs. description

***

### 9. Help Me Search

**Prompt:** `help_me_search`

**Use when:** You're unsure which search approach to use.

**Example queries:**

* "How do I find billing disputes?"
* "What's the best way to search for recent angry customers?"
* "Should I use tags or keywords for this search?"

**Arguments:**

* `what_you_want` (required): Description of what you're trying to find

**What it teaches:**

* Decision tree for choosing search tools
* Understanding exact match vs. keyword vs. semantic search
* Query optimization strategies
* Common pitfalls to avoid

***

## How to Use Prompts

### In Claude Desktop or Compatible MCP Clients

1. **List available prompts:** The client will automatically discover prompts from the server.
2. **Select a prompt:** Choose the prompt that matches your use case.
3. **Fill in arguments:** Provide the required information (e.g., search criteria, date range).
4. **Execute:** The prompt will guide you with a detailed strategy and example tool calls.

### Example Workflow

**User Goal:** Find angry customers from June

1. **Choose Prompt:** `find_by_exact_tags` (if you have sentiment tags) or `find_by_semantic_search` (for natural language)
2. **Provide Arguments:**
   * `tag_criteria`: "angry customers"
   * `date_range`: "from June"
3. **Follow Guidance:** The prompt will show:
   * How to parse "angry" into `{sentiment: "angry"}`
   * How to convert "June" to ISO 8601 dates
   * Which tool to call (`search_by_tags`)
   * Example JSON for the tool call
4. **Execute Tool:** Use the suggested tool with parameters
5. **Review Results:** Get matching vCons with UUIDs and details

***

## Search Strategy Decision Tree

Use this flowchart to choose the right prompt:

```
Do you know the exact tag value?
├─ YES → Use "find_by_exact_tags"
└─ NO
   ├─ Do you need specific words/phrases?
   │  └─ YES → Use "find_by_keywords"
   └─ NO
      ├─ Are you searching by meaning/concept?
      │  └─ YES → Use "find_by_semantic_search"
      └─ NO
         ├─ Is this a person/party search?
         │  └─ YES → Use "find_by_party"
         └─ NO
            ├─ Multiple criteria?
            │  └─ YES → Use "complex_search"
            └─ UNSURE → Use "help_me_search"
```

***

## Prompt Benefits

### 1. Educational

Prompts teach you:

* How the search tools work
* Best practices for each scenario
* Parameter optimization
* Error handling and fallbacks

### 2. Efficient

Prompts provide:

* Pre-structured queries
* Example JSON for tool calls
* Step-by-step guidance
* Time-saving templates

### 3. Comprehensive

Prompts cover:

* All search tool variations
* Date parsing and formatting
* Tag discovery and usage
* Multi-criteria combining

***

## Search Tool Reference

Here's a quick reference of the tools prompts will guide you to use:

| Tool                    | Purpose                 | Key Parameters                            |
| ----------------------- | ----------------------- | ----------------------------------------- |
| `search_vcons`          | Basic metadata search   | party\_name, party\_email, subject, dates |
| `search_vcons_content`  | Keyword search          | query, tags, dates                        |
| `search_vcons_semantic` | Semantic/meaning search | query, threshold, tags                    |
| `search_vcons_hybrid`   | Combined approach       | query, semantic\_weight, tags             |
| `search_by_tags`        | Exact tag matching      | tags (object), limit                      |
| `get_unique_tags`       | Discover available tags | include\_counts, key\_filter              |
| `get_vcon`              | Retrieve specific vCon  | uuid                                      |

***

## Common Use Cases

### Customer Service

* **Find escalated issues:** `find_by_exact_tags` with priority tags
* **Search complaints:** `find_by_semantic_search` for "complaints" or "issues"
* **Track a party's history:** `find_by_party` with email/phone

### Sales

* **High-value opportunities:** `find_by_exact_tags` with priority + department
* **Pricing discussions:** `find_by_keywords` searching for "pricing" or "quote"
* **Recent qualified leads:** `find_recent_by_topic` with "sales" topic

### Analytics

* **Sentiment analysis:** `find_by_exact_tags` or `find_by_semantic_search` for sentiment
* **Topic clustering:** `find_similar_conversations` to group related calls
* **Trend discovery:** `find_recent_by_topic` with time ranges

### Compliance

* **Audit trails:** `find_by_party` for specific party interactions
* **Keyword monitoring:** `find_by_keywords` for compliance terms
* **Tag validation:** `discover_available_tags` to review taxonomy

***

## Tips and Best Practices

### Start Broad, Then Narrow

1. Begin with `discover_available_tags` to see what's possible
2. Use `help_me_search` to understand the best approach
3. Execute the recommended search
4. Refine with additional filters if needed

### Use Date Filters Effectively

* **Relative:** "last week", "this month", "Q1"
* **Absolute:** "June 2024", "2024-01-01 to 2024-03-31"
* **Recent:** Defaults to last 30 days in most prompts

### Tag Strategy

* Use `get_unique_tags` first to discover what tags exist
* Tag searches are EXACT - "angry" won't match "frustrated"
* Combine tags with AND logic (all must match)
* Consider semantic search for fuzzy matching

### Semantic Search Considerations

* Requires pre-generated embeddings
* Works across synonyms and paraphrases
* Adjust threshold based on precision needs:
  * 0.6-0.7: Broader results
  * 0.7-0.8: Balanced
  * 0.8-0.9: Very similar only

### Performance Optimization

* Always use date filters for "recent" queries
* Limit results to what you need (10-50)
* Use tags to pre-filter before content search
* Start with exact matches, fall back to semantic

***

## Integration with Other Features

### With Resources

After finding vCons, access them via resources:

```
vcon://v1/vcons/{uuid}
```

### With Tags

Use prompts to search, then use tag tools to organize:

* `manage_tag` - Add/update/remove tags
* `get_tags` - View existing tags
* `remove_all_tags` - Clear tags

### With Database Tools

Combine prompt-guided searches with:

* `get_database_stats` - Analyze search performance
* `analyze_query` - Optimize slow searches

***

## Troubleshooting

### "No results found"

1. Try `discover_available_tags` to verify tags exist
2. Broaden date range or remove filters
3. Use semantic search for fuzzy matching
4. Check if embeddings are generated (for semantic search)

### "Embedding generation not yet implemented"

1. Fall back to `search_vcons_content` for keywords
2. Or generate embeddings using provided scripts
3. Or use `search_vcons_hybrid` with low semantic weight

### Too many results

1. Add date range filters
2. Include more specific tags
3. Use more specific keywords
4. Increase semantic threshold

### Wrong results

1. Verify tag values with `get_unique_tags`
2. Check date format (should be ISO 8601)
3. Try different search strategy (exact vs. semantic)
4. Use `help_me_search` prompt for guidance

***

## Next Steps

* **Try the prompts:** Start with `help_me_search` to explore
* **Learn the tools:** Each prompt teaches specific tool usage
* **Optimize queries:** Use insights to build better searches
* **Discover your data:** Use `discover_available_tags` to understand your corpus

For more information:

* [Search Guide](/guide/search) - Detailed search tool documentation
* [Tags Guide](/guide/tags) - Tag system documentation
* [Getting Started](/guide/getting-started) - Getting started guide


# Database Tools

## Overview

The vCon MCP server provides three powerful tools for database debugging, performance monitoring, and optimization.

## Available Tools

### 1. `get_database_shape` - Database Structure Inspector

Get comprehensive information about your database structure including tables, indexes, sizes, and relationships.

**Use Cases:**

* Understanding database schema
* Checking table and index sizes
* Identifying relationships between tables
* Database documentation

**Parameters:**

```json
{
  "include_counts": true,    // Include row counts (default: true)
  "include_sizes": true,     // Include disk sizes (default: true)
  "include_indexes": true,   // Include index info (default: true)
  "include_columns": false   // Include column details (default: false)
}
```

**Example Request:**

```json
{
  "tool": "get_database_shape",
  "arguments": {
    "include_counts": true,
    "include_sizes": true,
    "include_indexes": true,
    "include_columns": false
  }
}
```

**Example Response:**

```json
{
  "success": true,
  "database_shape": {
    "timestamp": "2024-10-14T12:00:00Z",
    "tables": [
      {
        "name": "vcons",
        "schema": "public",
        "row_count": 4443,
        "total_size": "1024 kB",
        "table_size": "896 kB",
        "indexes_size": "128 kB",
        "indexes": [
          {
            "indexname": "vcons_pkey",
            "index_type": "btree",
            "index_size": "48 kB"
          },
          {
            "indexname": "idx_vcons_uuid",
            "index_type": "btree",
            "index_size": "40 kB"
          }
        ]
      }
    ],
    "relationships": [
      {
        "from_table": "dialog",
        "from_column": "vcon_id",
        "to_table": "vcons",
        "to_column": "id"
      }
    ]
  }
}
```

**What You Get:**

* ✅ Table names and schemas
* ✅ Row counts for each table
* ✅ Disk sizes (table + indexes)
* ✅ Index information (name, type, size)
* ✅ Column definitions (optional)
* ✅ Foreign key relationships

***

### 2. `get_database_stats` - Performance & Usage Statistics

Get detailed performance metrics, cache statistics, and table access patterns.

**Use Cases:**

* Performance monitoring
* Identifying hot tables
* Finding unused indexes
* Cache optimization
* Query pattern analysis

**Parameters:**

```json
{
  "include_query_stats": true,   // Table access patterns (default: true)
  "include_index_usage": true,   // Index usage stats (default: true)
  "include_cache_stats": true,   // Cache hit ratios (default: true)
  "table_name": null             // Optional: specific table
}
```

**Example Request:**

```json
{
  "tool": "get_database_stats",
  "arguments": {
    "include_query_stats": true,
    "include_index_usage": true,
    "include_cache_stats": true
  }
}
```

**Example Response:**

```json
{
  "success": true,
  "database_stats": {
    "timestamp": "2024-10-14T12:00:00Z",
    "cache_stats": {
      "hit_ratio": "0.9850",
      "heap_blocks_hit": 123456,
      "heap_blocks_read": 1876
    },
    "table_stats": [
      {
        "table_name": "vcons",
        "sequential_scans": 45,
        "sequential_rows_read": 199935,
        "index_scans": 8934,
        "index_rows_fetched": 12456,
        "inserts": 4443,
        "updates": 234,
        "deletes": 12,
        "live_rows": 4431,
        "dead_rows": 15
      }
    ],
    "index_usage": [
      {
        "table_name": "vcons",
        "index_name": "idx_vcons_uuid",
        "scans": 8934,
        "rows_read": 8934,
        "rows_fetched": 8934
      }
    ],
    "unused_indexes": [
      {
        "table_name": "old_table",
        "index_name": "idx_old_field",
        "index_size": "24 MB"
      }
    ]
  }
}
```

**What You Get:**

#### Cache Statistics

* **Hit Ratio**: Percentage of reads served from cache (higher is better)
* **Blocks Hit**: Number of times data was found in cache
* **Blocks Read**: Number of times data had to be read from disk

**Recommended Action:**

* Hit ratio < 90%: Consider increasing shared\_buffers
* Hit ratio > 99%: Cache is well-tuned

#### Table Access Patterns

* **Sequential Scans**: Full table scans (may indicate missing indexes)
* **Index Scans**: Index-based access (efficient)
* **Modifications**: Inserts, updates, deletes
* **Dead Rows**: Rows marked for deletion (may need VACUUM)

**Recommended Actions:**

* High sequential scans on large tables: Add indexes
* Many dead rows: Run VACUUM ANALYZE
* Low index usage: Index might not be optimal

#### Index Usage

* **Scans**: How many times the index was used
* **Rows Fetched**: How many rows were accessed via index

**Recommended Actions:**

* Scans = 0: Index is unused, consider dropping
* Many scans: Index is valuable, keep it

#### Unused Indexes

Lists indexes that have never been used since stats reset.

**Recommended Actions:**

* Drop unused indexes to improve write performance
* Each index slows down INSERT/UPDATE/DELETE operations
* Keep only indexes that provide query benefits

***

### 3. `analyze_query` - Query Performance Analysis

Analyze SQL query execution plans to understand performance characteristics. Uses the dedicated `explain_query` database function — both modes are fully supported.

**Use Cases:**

* Understanding query performance
* Identifying slow queries
* Optimizing index usage
* Planning query improvements

**Parameters:**

```json
{
  "query": "SELECT ...",          // SQL query to analyze (SELECT only)
  "analyze_mode": "explain"       // "explain" or "explain_analyze"
}
```

**Modes:**

* `explain`: Generate execution plan without running the query (fast, safe)
* `explain_analyze`: Execute the query and measure actual performance — use with care on large tables, as it runs the full query

**Restrictions:**

* Only SELECT queries are allowed (enforced server-side)

**Reading the output:**

* `cost=X..Y` — estimated startup and total cost (arbitrary units, lower is better)
* `actual time=X..Y` — real milliseconds for first row\..last row
* `Buffers: shared hit=N read=M` — N pages from cache, M from disk; high hit ratio means good caching
* `Index Scan` / `Index Only Scan` — query is using an index (good); `Seq Scan` on large tables may indicate a missing index

**Example output:**

```
Limit  (cost=0.42..6.12 rows=100 width=77) (actual time=1.4..2.3 rows=100 loops=1)
  ->  Index Scan Backward using idx_vcons_created_at on vcons
        Buffers: shared hit=95 read=3
Planning Time: 0.4 ms
Execution Time: 2.3 ms
```

***

## Common Use Cases

### 1. Database Health Check

```bash
# Get complete database overview
Tool: get_database_shape
Arguments: { "include_counts": true, "include_sizes": true }

# Check performance metrics
Tool: get_database_stats
Arguments: { "include_cache_stats": true }
```

Look for:

* Large table sizes (may need partitioning)
* Many dead rows (run VACUUM)
* Low cache hit ratio (tune memory)

### 2. Performance Optimization

```bash
# Find unused indexes
Tool: get_database_stats
Arguments: { "include_index_usage": true }

# Check table access patterns
Tool: get_database_stats
Arguments: { "include_query_stats": true }
```

Actions:

* Drop unused indexes
* Add indexes for high sequential scan tables
* Monitor index vs sequential scan ratios

### 3. Growth Monitoring

```bash
# Track table sizes over time
Tool: get_database_shape
Arguments: { "include_sizes": true, "include_counts": true }
```

Monitor:

* Row count growth
* Disk space usage
* Index size growth

### 4. Index Optimization

```bash
# Get all index information
Tool: get_database_shape
Arguments: { "include_indexes": true, "include_sizes": true }

# Check which indexes are being used
Tool: get_database_stats
Arguments: { "include_index_usage": true }
```

Strategy:

* Drop unused indexes (0 scans)
* Consolidate overlapping indexes
* Add indexes for frequently scanned tables

***

## Performance Metrics Interpretation

### Cache Hit Ratio

| Ratio  | Status    | Action                                  |
| ------ | --------- | --------------------------------------- |
| > 99%  | Excellent | No action needed                        |
| 95-99% | Good      | Monitor                                 |
| 90-95% | Fair      | Consider increasing shared\_buffers     |
| < 90%  | Poor      | Increase shared\_buffers, check queries |

### Sequential vs Index Scans

| Scenario                    | Interpretation | Action                          |
| --------------------------- | -------------- | ------------------------------- |
| High seq scans, small table | OK             | Small tables are fine to scan   |
| High seq scans, large table | Problem        | Add index                       |
| High index scans            | Good           | Indexes working well            |
| Low scans overall           | Variable       | Check if table is actively used |

### Dead Rows

| Dead Rows         | Action                 |
| ----------------- | ---------------------- |
| < 5% of live rows | OK                     |
| 5-20%             | Schedule VACUUM        |
| > 20%             | Run VACUUM immediately |

***

## Best Practices

### 1. Regular Health Checks

Run these tools:

* **Daily**: get\_database\_stats (cache, hot tables)
* **Weekly**: get\_database\_shape (sizes, growth)
* **Monthly**: Full analysis (unused indexes, optimization opportunities)

### 2. Performance Tuning Workflow

1. **Identify** slow areas using get\_database\_stats
2. **Analyze** specific queries (if supported)
3. **Optimize** by adding/dropping indexes
4. **Monitor** improvements with stats

### 3. Index Management

**When to add an index:**

* High sequential scans on large table
* Frequent WHERE/JOIN conditions on column
* Slow queries using that column

**When to drop an index:**

* 0 scans in index\_usage
* Overlaps with another index
* Table is write-heavy and read-light

### 4. Maintenance Schedule

Based on database stats:

* **VACUUM**: When dead rows > 10%
* **ANALYZE**: After large data changes
* **REINDEX**: If index bloat suspected

***

## Example Workflow: Finding and Fixing Performance Issues

### Step 1: Check Overall Health

```json
{
  "tool": "get_database_stats",
  "arguments": {
    "include_cache_stats": true,
    "include_query_stats": true
  }
}
```

### Step 2: Identify Problem Tables

Look for:

* Tables with high sequential scans
* Tables with many dead rows
* Low cache hit ratios

### Step 3: Check Indexes

```json
{
  "tool": "get_database_shape",
  "arguments": {
    "include_indexes": true
  }
}
```

### Step 4: Review Index Usage

```json
{
  "tool": "get_database_stats",
  "arguments": {
    "include_index_usage": true,
    "table_name": "problematic_table"
  }
}
```

### Step 5: Take Action

* Add missing indexes
* Drop unused indexes
* Run VACUUM on tables with dead rows
* Tune cache settings if needed

***

## Test Script

Run the test script to see all tools in action:

```bash
npx tsx scripts/test-database-tools.ts
```

This will:

* Show database structure
* Display performance metrics
* Identify optimization opportunities
* Demonstrate all available features

***

## Troubleshooting

### "Permission denied" errors

* Ensure you're using SUPABASE\_SERVICE\_ROLE\_KEY (not anon key)
* Check that exec\_sql RPC has proper permissions

### "Function not found" errors

* Ensure migrations are applied: `supabase db reset`
* Check that exec\_sql RPC exists in your database

### Slow performance

* Run with smaller scope (single table)
* Disable expensive options (include\_columns, include\_sizes)
* Use table\_name parameter to focus on specific tables

***

## Related Documentation

* [Database Migrations](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/supabase/migrations/README.md) - Database schema
* [Search Optimization Guide](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/SEARCH_OPTIMIZATION_GUIDE.md) - Search performance
* [INGEST\_AND\_EMBEDDINGS.md](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/INGEST_AND_EMBEDDINGS.md) - Data ingestion

***

## Summary

The database inspection tools provide comprehensive visibility into your vCon database:

1. **`get_database_shape`** - Structure, sizes, relationships
2. **`get_database_stats`** - Performance, usage, optimization opportunities
3. **`analyze_query`** - Query execution analysis (limited support)

Use these tools to:

* Monitor database health
* Optimize performance
* Identify bottlenecks
* Plan capacity
* Debug issues

Regular use of these tools will help maintain a healthy, performant database.


# Troubleshooting

Common issues and solutions for the vCon MCP Server.

## Installation Issues

### Error: "Cannot find module 'dotenv'"

**Symptom:**

```
Error: Cannot find module 'dotenv'
```

**Cause:** Dependencies not installed

**Solution:**

```bash
npm install
```

***

### Error: "ENOENT: no such file or directory, open 'dist/index.js'"

**Symptom:**

```
Error: ENOENT: no such file or directory, open '/path/to/vcon-mcp/dist/index.js'
```

**Cause:** Project not built

**Solution:**

```bash
npm run build
```

***

### Error: "Invalid Supabase URL"

**Symptom:**

```
Error: Invalid Supabase URL or API key
```

**Cause:** Missing or incorrect environment variables

**Solution:**

1. Check `.env` file exists:

   ```bash
   cat .env
   ```
2. Verify format (no quotes needed):

   ```env
   SUPABASE_URL=https://your-project.supabase.co
   SUPABASE_ANON_KEY=eyJ...
   ```
3. Get correct values from Supabase:
   * Dashboard → Settings → API
   * Copy Project URL and anon public key

***

## Database Issues

### Error: "relation 'vcons' does not exist"

**Symptom:**

```
Error: relation "vcons" does not exist
```

**Cause:** Database migrations not applied

**Solution:**

**Option A: Using Supabase CLI**

```bash
npx supabase db push
```

**Option B: Manual via Dashboard**

1. Go to Supabase SQL Editor
2. Run each migration from `supabase/migrations/` in order
3. Verify tables created:

   ```sql
   SELECT table_name FROM information_schema.tables 
   WHERE table_schema = 'public';
   ```

***

### Error: "permission denied for table vcons"

**Symptom:**

```
Error: permission denied for table vcons
```

**Cause:** RLS policies not configured or using wrong key

**Solution:**

1. Check you're using the correct key (anon key, not service role key for testing)
2. Verify RLS policies exist:

   ```sql
   SELECT * FROM pg_policies WHERE tablename = 'vcons';
   ```
3. If missing, run RLS migration:

   ```bash
   # In Supabase SQL Editor
   -- Run: supabase/migrations/003_rls_policies.sql
   ```

***

### Database connection timeout

**Symptom:**

```
Error: Connection timeout
```

**Cause:** Network issues or invalid URL

**Solution:**

1. Test connection:

   ```bash
   curl "https://your-project.supabase.co/rest/v1/" \
     -H "apikey: your-anon-key"
   ```

   Should return 200 OK
2. Check Supabase project is active (not paused)
3. Verify URL format: `https://PROJECT_ID.supabase.co`

***

## Claude Desktop Issues

### Claude Desktop doesn't show vCon tools

**Symptom:** Claude doesn't list vCon tools when asked "What tools do you have?"

**Checklist:**

1. ✅ **Built the project**

   ```bash
   npm run build
   ls -la dist/index.js  # Should exist
   ```
2. ✅ **Used absolute path in config**

   ```bash
   # Get absolute path
   cd /path/to/vcon-mcp && pwd
   # Use: /full/path/to/vcon-mcp/dist/index.js
   ```
3. ✅ **Restarted Claude Desktop completely**
   * Quit Claude Desktop (not just close window)
   * Reopen Claude Desktop
   * Start new conversation
4. ✅ **.env file in project root**

   ```bash
   ls -la /path/to/vcon-mcp/.env  # Should exist
   ```
5. ✅ **Valid Supabase credentials**

   ```bash
   cat .env  # Check values
   ```

**Debug Steps:**

1. Test server directly:

   ```bash
   node dist/index.js
   ```

   Should output MCP initialization messages Press Ctrl+C to stop
2. Check config syntax:

   ```bash
   # macOS
   cat ~/Library/Application\ Support/Claude/claude_desktop_config.json
   ```

   Verify valid JSON (no trailing commas, proper brackets)
3. Check logs:
   * Open Claude Desktop
   * Help → View Logs
   * Look for MCP server errors

***

### Error: "spawn node ENOENT"

**Symptom:**

```
Error: spawn node ENOENT
```

**Cause:** Node.js not in PATH for Claude Desktop

**Solution:**

**macOS:**

```json
{
  "mcpServers": {
    "vcon": {
      "command": "/usr/local/bin/node",  // Full path to node
      "args": ["/absolute/path/to/vcon-mcp/dist/index.js"]
    }
  }
}
```

Find node path:

```bash
which node
```

***

### Claude can't find vCons

**Symptom:**

```
No vCons found
```

**Cause:** Empty database

**Solution:**

Create test vCon:

```
Create a vCon with subject "Test" and party "Alice"
```

Verify in database:

```sql
SELECT uuid, subject FROM vcons;
```

***

## Runtime Errors

### Error: "vCon validation failed"

**Symptom:**

```
Error: vCon validation failed: [validation details]
```

**Cause:** Invalid vCon data structure

**Solution:**

1. Check error message for specific field
2. Verify required fields:
   * `vcon` version (e.g., "0.4.0")
   * `uuid` (valid UUID)
   * `created_at` (ISO 8601 timestamp)
   * At least one `party`
3. Use valid values:

   ```typescript
   {
     vcon: "0.4.0",
     uuid: "valid-uuid-here",
     created_at: "2025-01-15T10:00:00Z",
     parties: [{
       name: "Alice"
     }]
   }
   ```

***

### Error: "Analysis vendor required"

**Symptom:**

```
Error: Analysis must have vendor field
```

**Cause:** Missing required `vendor` field in analysis

**Solution:**

Always include `vendor` when adding analysis:

```
Add transcript analysis with vendor "OpenAI"
```

***

### Error: "Invalid UUID format"

**Symptom:**

```
Error: Invalid UUID format
```

**Cause:** Malformed UUID

**Solution:**

Use valid UUID v4 format:

```
abc12345-1234-1234-1234-123456789abc
```

Get UUID from vCon list:

```
Show me recent vCons
```

***

## Search Issues

### Semantic search not working

**Symptom:**

```
Error: Semantic search requires embeddings
```

**Cause:** Embeddings not configured or generated

**Solution:**

1. Enable pgvector extension:

   ```sql
   CREATE EXTENSION IF NOT EXISTS vector;
   ```
2. Run vector migrations:

   ```bash
   # In Supabase SQL Editor
   -- Run: supabase/migrations/005_vector_extension.sql
   -- Run: supabase/migrations/006_embeddings_table.sql
   ```
3. Add OpenAI API key:

   ```bash
   echo "OPENAI_API_KEY=sk-your-key" >> .env
   ```
4. Generate embeddings:

   ```bash
   npm run scripts/generate-embeddings-v2.ts
   ```

***

### Search returns no results

**Symptom:** Search finds nothing when data exists

**Cause:** Various possibilities

**Solutions:**

1. **Check data exists:**

   ```
   Show me all vCons
   ```
2. **Try simpler search:**

   ```
   Find vCons from the last month
   ```
3. **Check search mode:**
   * Basic search: subject/party/dates only
   * Keyword search: full-text in dialog/analysis
   * Semantic search: requires embeddings
4. **Verify content is searchable:**
   * Dialog must have `encoding: "none"` for keyword search
   * Attachments not included in search

***

## Performance Issues

### Slow queries

**Symptom:** Queries take >2 seconds

**Cause:** Missing indexes or large dataset

**Solution:**

1. Check indexes exist:

   ```sql
   SELECT * FROM pg_indexes WHERE tablename IN ('vcons', 'dialog', 'analysis');
   ```
2. Run index migration:

   ```bash
   # In Supabase SQL Editor
   -- Run: supabase/migrations/002_indexes.sql
   ```
3. Analyze tables:

   ```sql
   ANALYZE vcons;
   ANALYZE dialog;
   ANALYZE analysis;
   ```
4. Check database stats:

   ```
   Show me database performance stats
   ```

***

### Out of memory

**Symptom:**

```
Error: JavaScript heap out of memory
```

**Cause:** Large dataset operations

**Solution:**

1. Increase Node.js memory:

   ```bash
   node --max-old-space-size=4096 dist/index.js
   ```
2. Use pagination in searches:

   ```
   Find first 10 vCons from January
   ```
3. Use resources for simple reads:

   ```
   Read vcon://v1/vcons/abc-123/metadata
   ```

***

## Testing Issues

### Tests fail with "database connection error"

**Symptom:**

```
Error: Database connection failed
```

**Cause:** Test environment not configured

**Solution:**

1. Create `.env.test` file:

   ```bash
   cp .env .env.test
   ```
2. Use test database (separate from production):

   ```env
   SUPABASE_URL=https://test-project.supabase.co
   SUPABASE_ANON_KEY=test-key
   ```
3. Run migrations on test database
4. Run tests:

   ```bash
   npm test
   ```

***

### Tests pass but code fails

**Symptom:** Tests succeed but actual usage fails

**Cause:** Different environment (test vs production)

**Solution:**

1. Verify `.env` vs `.env.test` settings
2. Check both databases have same schema
3. Test with production credentials (carefully)
4. Add integration tests:

   ```bash
   npm run test:integration
   ```

***

## Plugin Issues

### Plugin not loading

**Symptom:**

```
Error: Could not load plugin: ./my-plugin.js
```

**Cause:** Plugin path or format incorrect

**Solution:**

1. Verify plugin path:

   ```bash
   ls -la ./my-plugin.js  # Should exist
   ```
2. Check plugin format:

   ```typescript
   export default class MyPlugin {
     name = 'my-plugin';
     version = '1.0.0';
     // ... implementation
   }
   ```
3. Check environment variable:

   ```bash
   echo $VCON_PLUGINS_PATH
   ```
4. Test plugin loading:

   ```bash
   node -e "require('./my-plugin.js')"
   ```

***

## Build Issues

### TypeScript compilation errors

**Symptom:**

```
Error: TypeScript compilation failed
```

**Solution:**

1. Check TypeScript version:

   ```bash
   npx tsc --version  # Should be 5.x
   ```
2. Clean and rebuild:

   ```bash
   rm -rf dist node_modules
   npm install
   npm run build
   ```
3. Fix type errors shown in output

***

### Missing dependencies

**Symptom:**

```
Error: Cannot find module '@modelcontextprotocol/sdk'
```

**Solution:**

```bash
npm install
```

If persists:

```bash
rm -rf node_modules package-lock.json
npm install
```

***

## Getting More Help

### Debug Mode

Enable detailed logging:

```bash
LOG_LEVEL=debug node dist/index.js
```

### Verbose Tests

```bash
npm test -- --reporter=verbose
```

### Check System Status

```bash
# Node.js
node --version

# npm
npm --version

# Dependencies
npm list --depth=0

# Build status
ls -la dist/

# Environment
cat .env
```

### Report Issues

If you can't resolve an issue:

1. **Search existing issues:** [GitHub Issues](https://github.com/vcon-dev/vcon-mcp/issues)
2. **Create new issue with:**
   * Error message (full text)
   * Steps to reproduce
   * Environment details (OS, Node.js version, etc.)
   * Relevant config (sanitized, no keys)
3. **Ask in discussions:** [GitHub Discussions](https://github.com/vcon-dev/vcon-mcp/discussions)

***

## Quick Fixes

### "It just doesn't work"

Try this sequence:

```bash
# 1. Clean everything
rm -rf node_modules dist

# 2. Reinstall
npm install

# 3. Rebuild
npm run build

# 4. Test
npm test

# 5. Verify env
cat .env

# 6. Test server
node dist/index.js
# Should see initialization messages
# Press Ctrl+C

# 7. Restart Claude Desktop
# Quit completely and reopen
```

### Reset to fresh state

```bash
# Backup first!
cp -r vcon-mcp vcon-mcp.backup

# Clean
git clean -fdx
git reset --hard

# Reinstall
npm install
npm run build

# Reconfigure
cp .env.example .env
# Edit .env with your credentials
```

***

**Still stuck?** [Ask for help](https://github.com/vcon-dev/vcon-mcp/discussions) →

**Found a bug?** [Report it](https://github.com/vcon-dev/vcon-mcp/issues) →


# FAQ

Common questions about the vCon MCP Server.

## General

### What is vCon?

vCon (Virtual Conversation) is an IETF standard format for representing conversations in a portable, interoperable way. Think of it as "PDF for conversations" - a standardized container that includes:

* Conversation content (voice, video, text, email)
* Participants (parties) with identity information
* AI analysis results (transcripts, sentiment, summaries)
* Attachments (documents, images, files)
* Privacy markers for consent and redaction

**Learn more:** [IETF vCon Specification](/reference/vcon-spec)

***

### What is MCP?

MCP (Model Context Protocol) is an open standard that enables AI assistants to interact with external tools and data sources. Instead of being limited to training data, AI assistants can:

* Access real-time data from databases and APIs
* Perform actions using external tools
* Read and write to external systems
* Maintain context across conversations

**Learn more:** [modelcontextprotocol.io](https://modelcontextprotocol.io/)

***

### Why use vCon MCP Server?

The vCon MCP Server gives AI assistants like Claude the ability to:

* **Store** conversation data in a standard format
* **Search** through historical conversations
* **Analyze** conversations for insights
* **Organize** with tags and metadata
* **Query** using natural language

It combines the power of IETF vCon with the flexibility of MCP.

***

### Is it free?

**Yes!** The vCon MCP Server is open source under the MIT License. The core features are completely free to use.

**Dependencies:**

* Node.js - Free, open source
* Supabase - Free tier available (upgrade for production)
* OpenAI (optional) - Pay per use for semantic search embeddings

**Optional:**

* Enterprise plugins - May require licenses
* Professional support - Contact for pricing

***

### What's the catch?

No catch! This is a genuine open-source project implementing IETF standards.

**Costs you might incur:**

* Supabase (free tier usually sufficient for development)
* OpenAI API (only if using semantic search)
* Hosting (if deploying to production)

***

## Installation & Setup

### Do I need to know TypeScript?

**For using:** No, just use Claude Desktop with natural language.

**For extending:** Basic TypeScript knowledge helpful for plugins/custom tools.

**For contributing:** Yes, the project is written in TypeScript.

***

### Can I use it without Claude Desktop?

**Yes!** The server works with any MCP client:

* Claude Desktop (easiest)
* Custom MCP clients
* Direct API calls to Supabase
* Command-line tools (coming soon)

***

### Do I need a Supabase account?

**Yes,** Supabase is required for database storage. The free tier is sufficient for:

* Development
* Small projects
* Testing
* Personal use

Upgrade to paid tier for:

* Production deployments
* Large datasets (>500MB)
* High traffic
* Priority support

**Alternative:** You can use self-hosted PostgreSQL with pgvector, but you'll need to adapt the code.

***

### Can I use a different database?

The server is built for Supabase/PostgreSQL. To use another database:

1. **PostgreSQL-compatible** (e.g., Amazon RDS, Google Cloud SQL) - Relatively easy
2. **Other SQL** (MySQL, SQLite) - Requires schema adaptation
3. **NoSQL** (MongoDB, DynamoDB) - Requires major refactoring

**Recommendation:** Stick with Supabase for best experience.

***

### How long does setup take?

**Quick setup:** 5 minutes (using Quick Start) **Complete setup:** 15-30 minutes (including database configuration) **Development setup:** 1-2 hours (including reading docs)

***

## Features & Capabilities

### What can I store in a vCon?

A vCon can contain:

* **Dialog**: Recordings, transcripts, text messages, video calls
* **Parties**: Participants with names, emails, phone numbers, roles
* **Analysis**: AI-generated insights (transcripts, sentiment, summaries)
* **Attachments**: Related files, documents, images
* **Metadata**: Subject, timestamps, extensions
* **Tags**: Custom key-value pairs for organization

**Essentially:** Any conversation data plus related analysis and files.

***

### How does search work?

Four search modes:

1. **Basic filtering** - By subject, party name, dates
2. **Keyword search** - Full-text search across dialog and analysis
3. **Semantic search** - AI-powered meaning-based search (requires embeddings)
4. **Hybrid search** - Combines keyword and semantic for best results

***

### Do I need OpenAI for search?

**No** for basic, keyword, and hybrid keyword-based search.

**Yes** for semantic search (requires embeddings):

* OpenAI API for generating embeddings
* Or use local embedding models (more setup)

**Recommendation:** Start without OpenAI, add semantic search later if needed.

***

### What's the difference between tools, resources, and prompts?

* **Tools** - Actions AI can perform (create, search, update, delete)
* **Resources** - Read-only data access (like URLs)
* **Prompts** - Guidance for effective searching

Example:

* **Tool:** `create_vcon` - Creates new vCon
* **Resource:** `vcon://v1/vcons/recent` - Reads recent vCons
* **Prompt:** `find_by_tags` - Guides tag-based search

***

### Can I use this in production?

**Yes,** with proper configuration:

1. Use Supabase paid tier (not free tier)
2. Configure Row Level Security (RLS)
3. Set up monitoring and logging
4. Use service role key for admin operations
5. Enable backups
6. Configure rate limiting

See [Production Deployment](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/deployment/README.md) for details.

***

## Data & Privacy

### Is my conversation data secure?

Security depends on your configuration:

**Built-in security:**

* Supabase uses encrypted connections (TLS)
* Row Level Security (RLS) for multi-tenancy
* API key authentication
* No data stored on our servers (you control the database)

**Your responsibility:**

* Keep API keys secure
* Configure RLS policies properly
* Use HTTPS for client connections
* Regular security audits

***

### Can I use this for HIPAA/GDPR compliance?

The server **supports** compliance features but is not automatically compliant:

**What's included:**

* Consent tracking fields
* Redaction support
* Privacy markers
* Audit trail capabilities
* Plugin hooks for compliance

**What you need to do:**

* Configure compliance plugins
* Set up proper access controls
* Implement data retention policies
* Conduct security assessments
* Sign BAA with Supabase (for HIPAA)

**Recommendation:** Consult with compliance experts for production use.

***

### Where is data stored?

Your data lives in your Supabase project:

* **Default:** Supabase cloud (US, EU, or Asia depending on project region)
* **Optional:** Self-hosted PostgreSQL (full control)

**The vCon MCP Server never stores your data** - it only facilitates access.

***

### Can I export my data?

**Yes!** Multiple options:

1. **Supabase Dashboard** - Export to CSV, JSON
2. **PostgreSQL tools** - pg\_dump, pg\_restore
3. **API** - Fetch via REST API
4. **Batch export** - Coming soon

vCon format is portable - you can move to any system that supports the standard.

***

## Technical Questions

### What is the vCon specification version?

This implementation follows **`draft-ietf-vcon-vcon-core-02`**.

**Important:** This implementation corrects several common mistakes found in other implementations. See [Implementation Corrections](/reference/implementation_corrections) for details.

***

### Why not use the vcon package from npm?

Many existing vCon implementations have errors:

❌ **Common mistakes:**

* Wrong field names (`schema_version` instead of `schema`)
* Missing required fields (`vendor` in analysis)
* Wrong data types (`body` as object instead of string)
* Default encoding values (spec says no defaults)

✅ **This implementation:**

* 100% spec-compliant
* All corrections applied
* Thoroughly tested
* Well-documented

***

### What Node.js version do I need?

**Minimum:** Node.js 18.0

**Recommended:** Node.js 20.x (LTS)

**Why 18+:** Required for:

* ESM module support
* Modern JavaScript features
* Supabase SDK compatibility

Check version:

```bash
node --version
```

***

### Can I use this with Python?

Not directly, but you can:

1. **Use Supabase REST API** - Call from Python
2. **Create Python MCP client** - Implement MCP protocol
3. **Use subprocess** - Call Node.js server from Python

**Recommendation:** Use Supabase REST API for Python integration.

***

### Why TypeScript?

TypeScript provides:

* **Type safety** - Catch errors at compile time
* **Better IDE support** - Autocomplete, inline docs
* **Maintainability** - Easier to refactor
* **Documentation** - Types are self-documenting
* **vCon spec compliance** - Types match spec exactly

***

## Usage Questions

### How do I phrase questions to Claude?

Use natural language - Claude understands intent:

✅ **Good examples:**

* "Create a vCon for a customer support call"
* "Find conversations about billing issues"
* "Show me negative sentiment calls from last week"

❌ **Don't use:**

* Function syntax: `create_vcon({...})`
* SQL queries directly
* Technical field names (Claude handles this)

***

### Can Claude make mistakes?

**Yes,** AI assistants can:

* Misinterpret your request
* Use wrong search strategy
* Generate invalid UUIDs
* Miss edge cases

**Best practices:**

* Be specific in requests
* Verify critical operations
* Use test data first
* Review results before acting

***

### How do I undo an operation?

**Create/Update:** Can't undo - vCon spec favors immutability **Delete:** Can't undo - permanent deletion

**Best practices:**

* Test with non-production data first
* Keep database backups
* Use version control for configs
* Review before deleting

***

### Can I bulk import conversations?

**Yes,** multiple options:

1. **Ask Claude to create multiple:**

   ```
   Create 10 vCons for the conversations in this spreadsheet
   ```
2. **Use scripts:**

   ```bash
   npm run scripts/load-vcons.ts
   ```
3. **Direct database insert:**

   ```sql
   INSERT INTO vcons ...
   ```

See [Examples](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/examples/README.md) for details.

***

## Performance & Scaling

### How many vCons can I store?

**Limits depend on Supabase tier:**

* **Free tier:** 500MB database (thousands of vCons)
* **Pro tier:** 8GB database (hundreds of thousands)
* **Enterprise:** Custom (millions+)

**Also consider:**

* File attachments (use external storage)
* Search performance (use indexes)
* API rate limits

***

### How fast is search?

**Typical response times:**

* **By UUID:** <100ms (indexed)
* **Basic filtering:** <500ms (indexed)
* **Keyword search:** 500ms-2s (depends on dataset)
* **Semantic search:** 1-3s (vector similarity)

**Optimization tips:**

* Add indexes for common queries
* Use tags to pre-filter
* Limit result sets
* Cache frequent queries

***

### Can I use this at scale?

**Yes,** with proper architecture:

1. **Database:** Supabase Enterprise or self-hosted PostgreSQL
2. **Connection pooling:** PgBouncer
3. **Caching:** Redis for frequent queries
4. **Load balancing:** Multiple server instances
5. **Monitoring:** Performance tracking

See [Performance Guide](/deployment/performance) for details.

***

## Customization & Extension

### Can I add custom fields to vCons?

**Yes,** using extensions:

```
Add extension "priority" with value "high" to this vCon
```

Extensions are part of the vCon spec for custom metadata.

***

### How do I create a plugin?

See [Plugin Development Guide](/development/plugins).

**Quick example:**

```typescript
export default class MyPlugin {
  name = 'my-plugin';
  version = '1.0.0';
  
  async afterCreate(vcon, context) {
    console.log(`Created: ${vcon.uuid}`);
  }
}
```

***

### Can I add custom tools?

**Yes!** See [Custom Tools Guide](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/custom-tools.md).

Example: Add a tool to export vCons to PDF.

***

## Troubleshooting

### Claude doesn't see the tools

**Common fixes:**

1. Restart Claude Desktop completely
2. Check config file path (must be absolute)
3. Verify `dist/index.js` exists
4. Check `.env` file has Supabase credentials
5. Test server: `node dist/index.js`

See [Troubleshooting Guide](/guide/troubleshooting) for more.

***

### Search returns no results

**Possible causes:**

1. Database is empty - create test vCon
2. Wrong search mode - try basic filtering first
3. No matching results - broaden criteria
4. Indexes missing - run migration

***

### Tests fail

```bash
# Clean and rebuild
rm -rf node_modules dist
npm install
npm run build
npm test
```

See [Troubleshooting Guide](/guide/troubleshooting) for more.

***

## Contributing

### How can I contribute?

Many ways to help:

* **Report bugs** - GitHub Issues
* **Suggest features** - GitHub Discussions
* **Fix issues** - Submit PRs
* **Improve docs** - Edit documentation
* **Answer questions** - Help in Discussions
* **Share examples** - Real-world use cases

See [Contributing Guide](/development/contributing) for details.

***

### Do I need to sign a CLA?

**No CLA required.** By contributing, you agree your contributions are licensed under MIT License.

***

### What if I found a security issue?

**Please report privately** instead of public issues:

1. Email maintainers (see README)
2. Include detailed description
3. Wait for response before public disclosure

***

## Getting Help

### Where can I get help?

1. **Documentation** - Browse `/docs`
2. **Troubleshooting** - [Troubleshooting Guide](/guide/troubleshooting)
3. **GitHub Discussions** - Ask questions
4. **GitHub Issues** - Report bugs
5. **Community Discord** - Real-time chat (coming soon)

***

### How do I report a bug?

1. Search existing issues first
2. Create new issue with:
   * Clear title
   * Steps to reproduce
   * Expected vs actual behavior
   * Environment details
   * Error messages (full text)

***

### Can I get commercial support?

Professional support available:

* Priority bug fixes
* Custom feature development
* Deployment assistance
* Training and consulting

Contact for details (see README).

***

## Roadmap

### What's coming next?

**v1.1.0:**

* Real-time subscriptions
* Batch operations
* Enhanced analytics
* More examples

**v1.2.0:**

* CLI tool
* More integrations
* Advanced plugins
* Performance optimizations

**v2.0.0:**

* Multi-tenant architecture
* GraphQL API
* Real-time collaboration
* Enterprise features

See [Changelog](/reference/changelog) for details.

***

### Can I request features?

**Yes!** Feature requests welcome:

1. Check existing feature requests
2. Create GitHub Discussion or Issue
3. Describe use case and benefits
4. Discuss with community
5. Vote on features you want

Popular requests prioritized in roadmap.

***

## Still Have Questions?

* **Ask in Discussions:** [GitHub Discussions](https://github.com/vcon-dev/vcon-mcp/discussions)
* **Check Documentation:** Browse `/docs` for detailed guides
* **Join Community:** Discord (coming soon)

***

**Didn't find your answer?** [Ask a question](https://github.com/vcon-dev/vcon-mcp/discussions/new) →


# Overview

Complete API documentation for the vCon MCP Server.

## Overview

The vCon MCP Server provides a comprehensive API for managing virtual conversations through the Model Context Protocol (MCP). All interfaces are fully compliant with [IETF vCon Core](https://datatracker.ietf.org/doc/html/draft-ietf-vcon-vcon-core-02) specification.

For new MCP clients, start with the redesigned contract surface: `vcon_capabilities`, `vcon_taxonomy`, `vcon_search`, `vcon_fetch`, and `describe_response_shape`. The older tools remain available for backward compatibility and specialized workflows.

***

## API Components

### 🌐 [REST API](/api-reference/rest-api)

Full HTTP REST API with parity to all MCP tools (30+ endpoints):

* **vCon CRUD** - Create, read, update, delete + batch ingest
* **Discovery + Filtered Reads** - Discover live categories, then read by attachment `purpose` or analysis `type`
* **Sub-resources** - Read or append analysis and attachments, append dialog
* **Tags** - Per-vCon tag management + tag discovery
* **Search** - Keyword, semantic, and hybrid search
* **Database** - Schema shape, stats, size, health monitoring
* **Analytics** - Growth, content, tag, and attachment analytics
* **Infrastructure** - Health, version, schema, examples

[View REST API Reference →](/api-reference/rest-api)

***

### 🛠️ [Tools](/api-reference/tools)

46 MCP tools for vCon operations:

* **Redesigned Contract Tools** - Discovery-first search, fetch, and aggregation with predictable envelopes
* **Core Operations** - Create, read, update, delete vCons
* **Component Management** - Add, update, and remove parties, dialog, analysis, attachments
* **Search & Query** - Keyword, semantic, and hybrid search
* **Tag Management** - Organize with key-value metadata
* **Database Tools** - Inspect and optimize database
* **Schema & Examples** - Get schemas and example vCons

[View Tools Reference →](/api-reference/tools)

***

### 🔗 [Resources](/api-reference/resources)

URI-based access to vCon data:

* `vcon://v1/discovery/attachments/purposes` - Discover live attachment purposes
* `vcon://v1/discovery/attachments/types` - Discover legacy attachment types
* `vcon://v1/discovery/analysis/types` - Discover live analysis types
* `vcon://v1/vcons/recent` - Get recent vCons
* `vcon://v1/vcons/recent/ids` - Lightweight ID lists
* `vcon://v1/vcons/ids` - Paginated ID browsing
* `vcon://v1/vcons/{uuid}` - Get specific vCon
* `vcon://v1/vcons/{uuid}/metadata` - Get metadata only
* `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}` - Read attachments by purpose
* `vcon://v1/vcons/{uuid}/attachments/type/{type}` - Read attachments by legacy type
* `vcon://v1/vcons/{uuid}/analysis/type/{type}` - Read analysis by type

[View Resources Reference →](/api-reference/resources)

***

### 💬 [Prompts](/api-reference/prompts)

9 query template prompts:

* **find\_by\_exact\_tags** - Exact tag matching
* **find\_by\_semantic\_search** - AI-powered meaning search
* **find\_by\_keywords** - Keyword/phrase search
* **find\_recent\_by\_topic** - Recent conversations by topic
* **find\_by\_party** - Search by party
* **discover\_available\_tags** - Explore available tags
* **complex\_search** - Multi-criteria searches
* **find\_similar\_conversations** - Find similar vCons
* **help\_me\_search** - Query strategy guidance

[View Prompts Reference →](/api-reference/prompts)

***

### 📘 [Types](/api-reference/types)

TypeScript type definitions:

* **VCon** - Main conversation object
* **Party** - Conversation participants
* **Dialog** - Conversation segments
* **Analysis** - AI/ML analysis results
* **Attachment** - Additional files/data
* **Input/Output Types** - Tool parameters and responses

[View Types Reference →](/api-reference/types)

***

### 🗄️ [Database Schema](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/api/schema.md)

PostgreSQL/Supabase schema:

* **Core Tables** - vcons, parties, dialog, analysis, attachments
* **Search Tables** - vcon\_embeddings, vcon\_tags\_mv
* **Privacy Tables** - privacy\_requests (GDPR/CCPA)
* **RPC Functions** - search\_vcons\_keyword, search\_vcons\_semantic, search\_vcons\_hybrid
* **Indexes** - Performance optimization

[View Schema Reference →](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/api/schema.md)

***

## Quick Start Examples

### Create a vCon

```typescript
const result = await callTool("create_vcon", {
  vcon_data: {
    vcon: "0.4.0",
    subject: "Customer Support Call",
    parties: [
      {
        name: "Agent Smith",
        mailto: "smith@company.com"
      },
      {
        name: "John Doe",
        tel: "+1-555-1234"
      }
    ]
  }
});

console.log("Created vCon:", result.uuid);
```

### Search vCons

```typescript
// Discover search modes and include groups first
const capabilities = await callTool("vcon_capabilities", {});

// Unified keyword search
const results = await callTool("vcon_search", {
  mode: "keyword",
  query: "billing issue refund",
  filters: {
    tags: {
      department: "support",
      priority: "high"
    }
  },
  include: ["core", "summary", "dealer", "tags"],
  limit: 20
});
```

### Access via Resources

```typescript
// Get recent vCons
const recent = await readResource("vcon://v1/vcons/recent/10");

// Get specific vCon
const vcon = await readResource(
  "vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000"
);

// Discover live attachment purposes first
const purposes = await readResource("vcon://v1/discovery/attachments/purposes");

// Then read a specific category-backed view
const dealerInfo = await readResource(
  "vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/attachments/purpose/dealer_info"
);

// List IDs for navigation
const ids = await readResource("vcon://v1/vcons/recent/ids/50");
```

### Use Query Prompts

```typescript
// Get query guidance
const prompt = await getPrompt("find_by_exact_tags", {
  tag_criteria: "angry customers",
  date_range: "June 2024"
});

// Follow the prompt's strategy to execute search
```

***

## Architecture

### Protocol Flow

```
┌──────────────────────────────────────────────────────────────┐
│                        Clients                               │
├─────────────────────────────────┬────────────────────────────┤
│   AI Assistants (MCP)           │   External Systems (REST)  │
│   (Claude Desktop, Custom)      │   (Integrations, Pipelines)│
└───────────────┬─────────────────┴──────────────┬─────────────┘
                │ MCP (stdio/HTTP)                │ HTTP/JSON
                │                                 │
┌───────────────▼─────────────────────────────────▼────────────┐
│                     vCon MCP Server                          │
│  ┌──────────────────────────┬───────────────────────────┐    │
│  │   MCP Handlers           │   REST API (30+ routes)   │    │
│  │  - Tools (30+)           │  - CRUD + sub-resources   │    │
│  │  - Resources             │  - Tags + tag discovery   │    │
│  │  - Prompts               │  - Search (3 modes)       │    │
│  │                          │  - Database + analytics   │    │
│  │                          │  - Health, schema, docs   │    │
│  └────────────┬─────────────┴────────────┬──────────────┘    │
│               │                          │                   │
│  ┌────────────▼──────────────────────────▼──────────────┐    │
│  │               VCon Service                           │    │
│  │  - Lifecycle hooks (beforeCreate, afterCreate, ...)  │    │
│  │  - Validation                                        │    │
│  │  - Metrics                                           │    │
│  └────────────────────────┬─────────────────────────────┘    │
│                           │                                  │
│  ┌────────────────────────▼─────────────────────────────┐    │
│  │               Plugin Manager                         │    │
│  │  - Privacy plugins                                   │    │
│  │  - Access control                                    │    │
│  │  - Custom extensions                                 │    │
│  └────────────────────────┬─────────────────────────────┘    │
│                           │                                  │
└───────────────────────────┼──────────────────────────────────┘
                            │ Supabase Client
                            │
                 ┌──────────▼───────────┐
                 │      PostgreSQL      │
                 │      (Supabase)      │
                 │                      │
                 │  - vCon Tables       │
                 │  - pgvector          │
                 │  - GIN/GiST Indexes  │
                 └──────────────────────┘
```

### Data Flow

1. **Client Request** - Client calls MCP tool/resource
2. **Validation** - Zod schema validation
3. **Database Query** - PostgreSQL operations
4. **Processing** - Business logic, search, embeddings
5. **Response** - Formatted JSON response

***

## API Capabilities

### Search Modes

| Mode         | Best For         | Performance      | Accuracy       |
| ------------ | ---------------- | ---------------- | -------------- |
| **Metadata** | Exact filters    | Fast (\~50ms)    | Exact match    |
| **Keyword**  | Specific words   | Medium (\~100ms) | High precision |
| **Semantic** | Concepts/meaning | Slower (\~200ms) | Contextual     |
| **Hybrid**   | Best of both     | Slower (\~300ms) | Balanced       |
| **Tag**      | Categories       | Fast (\~50ms)    | Exact match    |

### Operations

| Operation  | Tool | Resource | Prompt |
| ---------- | ---- | -------- | ------ |
| **Create** | ✅    | ❌        | ❌      |
| **Read**   | ✅    | ✅        | ❌      |
| **Update** | ✅    | ❌        | ❌      |
| **Delete** | ✅    | ❌        | ❌      |
| **Search** | ✅    | ❌        | ✅      |
| **Browse** | ❌    | ✅        | ❌      |

***

## Standards Compliance

### vCon Specification

✅ **Draft IETF vCon Core 00**

* All required fields supported
* Optional extensions available
* Group references implemented
* Redaction/appending supported

### MCP Protocol

✅ **Model Context Protocol 1.0**

* Tools interface
* Resources interface
* Prompts interface
* Standard error handling

### Database

✅ **PostgreSQL 15+**

* Full SQL compliance
* JSONB support
* Array operations
* GIN/GiST/HNSW indexes

✅ **pgvector Extension**

* Vector similarity search
* Cosine distance
* HNSW indexing

***

## Authentication & Security

### Supabase Authentication

The server uses Supabase authentication:

```typescript
// Environment variables required
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_KEY=your-anon-key-here
```

### Row Level Security (RLS)

Optional RLS policies can be enabled:

```sql
-- Enable RLS on vcons table
ALTER TABLE vcons ENABLE ROW LEVEL SECURITY;

-- Example policy: Users can only see their own vCons
CREATE POLICY "Users can view own vCons"
  ON vcons FOR SELECT
  USING (auth.uid() = user_id);
```

### API Key Management

For production deployments:

1. Use service role key for server
2. Use anon key for clients
3. Implement RLS policies
4. Enable database audit logging

***

## Error Handling

All API responses include error information:

```typescript
interface ErrorResponse {
  success: false;
  error: string;
  details?: any;
}
```

### Common Error Codes

* `VALIDATION_ERROR` - Invalid input parameters
* `NOT_FOUND` - vCon or resource not found
* `DATABASE_ERROR` - Database operation failed
* `PERMISSION_DENIED` - Insufficient permissions

***

## Versioning

### API Version

Current: **1.2.0**

The API follows semantic versioning:

* **Major** - Breaking changes
* **Minor** - New features (backward compatible)
* **Patch** - Bug fixes

### vCon Version

Current: **0.4.0**

Follows IETF vCon specification versions.

***

## Next Steps

### For Users

1. [Getting Started Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/guide/getting-started.md)
2. [Search Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/guide/search.md)
3. [Tag Management Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/guide/tags.md)
4. [Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/examples/README.md)

### For Developers

1. [Development Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/development/README.md)
2. [Plugin Development](https://github.com/vcon-dev/vcon-mcp/tree/main/development/plugins.md)
3. [Testing Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/development/testing.md)
4. [Contributing](https://github.com/vcon-dev/vcon-mcp)

### Resources

* [IETF vCon Spec](https://datatracker.ietf.org/doc/html/draft-ietf-vcon-vcon-core-02)
* [Model Context Protocol](https://modelcontextprotocol.io/)
* [Supabase Docs](https://supabase.com/docs)
* [pgvector Docs](https://github.com/pgvector/pgvector)


# REST API

HTTP REST API for vCon ingestion and operations.

## Overview

The vCon MCP Server exposes a RESTful HTTP API alongside the MCP transport layer. This API provides endpoints for vCon CRUD operations, designed for programmatic integration with external systems.

### Key Features

* **HTTP/JSON** - Standard REST conventions
* **API Key Authentication** - Secure access with configurable API keys
* **CORS Support** - Configurable cross-origin resource sharing
* **Plugin Integration** - Full lifecycle hooks (beforeCreate, afterCreate, etc.)
* **Batch Operations** - Ingest up to 100 vCons in a single request
* **Discovery-Backed Reads** - Discover live attachment and analysis categories, then read by `type` or `purpose`
* **Health Checks** - Built-in health endpoint for monitoring

***

## Configuration

### REST API Variables

| Variable             | Default   | Description                      |
| -------------------- | --------- | -------------------------------- |
| `REST_API_BASE_PATH` | `/api/v1` | Base path for REST API endpoints |
| `REST_API_ENABLED`   | `true`    | Enable/disable REST API          |

### Authentication Variables

| Variable            | Default         | Description                                                                                                         |
| ------------------- | --------------- | ------------------------------------------------------------------------------------------------------------------- |
| `API_KEYS`          | (none)          | Comma-separated API keys with full read/write/delete access                                                         |
| `API_KEYS_READONLY` | (none)          | Comma-separated read-only API keys — authenticate, but any non-GET request returns `403 Forbidden`                  |
| `API_KEY_HEADER`    | `authorization` | Header for API key; default expects `Authorization: Bearer <token>`. Set to `x-api-key` to use that header instead. |
| `API_AUTH_REQUIRED` | `true`          | Set to `false` to disable authentication                                                                            |

### HTTP Transport Variables

The REST API requires HTTP transport mode to be enabled:

| Variable        | Default     | Description                         |
| --------------- | ----------- | ----------------------------------- |
| `MCP_TRANSPORT` | `stdio`     | Set to `http` to enable HTTP server |
| `MCP_HTTP_HOST` | `127.0.0.1` | HTTP host to bind                   |
| `MCP_HTTP_PORT` | `3000`      | HTTP port to listen on              |
| `CORS_ORIGIN`   | `*`         | CORS allowed origins                |

### Example Configuration

```bash
# Enable HTTP transport
MCP_TRANSPORT=http
MCP_HTTP_HOST=0.0.0.0
MCP_HTTP_PORT=3000

# Configure REST API (optional - defaults work for most cases)
REST_API_BASE_PATH=/api/v1
REST_API_ENABLED=true

# Configure authentication
API_KEYS=key1-abc123,key2-def456
API_AUTH_REQUIRED=true
```

***

## Authentication

All REST API endpoints (except `/health`) require API key authentication.

### Request Headers

By default, send your API key in the `Authorization` header:

```http
Authorization: Bearer your-api-key-here
```

You can use a different header by setting `API_KEY_HEADER` (e.g. `x-api-key`).

### Authentication Responses

**401 Unauthorized - Missing API Key:**

```json
{
  "error": "Unauthorized",
  "message": "Missing Authorization: Bearer <token> header"
}
```

**401 Unauthorized - Invalid API Key:**

```json
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

**503 Service Unavailable - Auth Not Configured:**

```json
{
  "error": "Service Unavailable",
  "message": "API authentication is required but not configured. Please contact the administrator.",
  "hint": "Set API_KEYS env var, or set API_AUTH_REQUIRED=false"
}
```

> **Note:** The `hint` field is only included in non-production environments.

***

## Endpoints

### Discovery-First Reads

When a classification is stored in attachments or analysis, prefer this sequence:

1. Discover available values first. For attachments, prefer `purpose`; use attachment `type` only for legacy compatibility. For analysis, use `type`.
2. Read the matching filtered vCon subresource.
3. Use tags when the classification genuinely lives in the tags attachment.

Examples:

```bash
# Discover live attachment purposes
curl "http://localhost:3000/api/v1/discovery/attachments/purposes" \
  -H "Authorization: Bearer your-api-key"

# Read one vCon's dealer info attachments
curl "http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000/attachments?purpose=dealer_info" \
  -H "Authorization: Bearer your-api-key"

# Read one vCon's summary analysis through the generic type filter
curl "http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000/analysis?type=summary" \
  -H "Authorization: Bearer your-api-key"
```

***

### Health Check

Check API and database health status.

**Endpoint:** `GET /api/v1/health`

**Authentication:** Not required

**Response (200 OK):**

```json
{
  "status": "healthy",
  "timestamp": "2025-01-02T10:30:00.000Z",
  "database": "connected"
}
```

**Response (503 Service Unavailable):**

```json
{
  "status": "unhealthy",
  "timestamp": "2025-01-02T10:30:00.000Z",
  "database": "error",
  "error": "Connection refused"
}
```

**Example:**

```bash
curl http://localhost:3000/api/v1/health
```

***

### Create vCon

Create/ingest a single vCon.

**Endpoint:** `POST /api/v1/vcons`

**Authentication:** Required

**Request Headers:**

```http
Content-Type: application/json
Authorization: Bearer your-api-key
```

**Request Body:**

The request body should be the vCon object directly:

```json
{
  "vcon": "0.4.0",
  "uuid": "optional-custom-uuid",
  "subject": "Customer Support Call",
  "parties": [
    {
      "name": "Agent Smith",
      "mailto": "smith@company.com",
      "role": "agent"
    },
    {
      "name": "John Doe",
      "tel": "+1-555-1234",
      "role": "customer"
    }
  ],
  "dialog": [
    {
      "type": "text",
      "start": "2025-01-02T10:00:00Z",
      "parties": [0, 1],
      "originator": 1,
      "body": "Hello, I need help with my account."
    }
  ],
  "analysis": [],
  "attachments": []
}
```

**Response (201 Created):**

```json
{
  "success": true,
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "id": "42",
  "message": "vCon created successfully",
  "duration_ms": 45
}
```

**Response (400 Bad Request - Validation Error):**

```json
{
  "error": "Validation Error",
  "message": "Missing required field: parties; Invalid party: must have at least one identifier"
}
```

**Example:**

```bash
curl -X POST http://localhost:3000/api/v1/vcons \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '{
    "vcon": "0.4.0",
    "subject": "Sales Call",
    "parties": [
      {"name": "Sales Rep", "mailto": "rep@company.com"},
      {"name": "Customer", "tel": "+1-555-9876"}
    ]
  }'
```

***

### Batch Create vCons

Ingest multiple vCons in a single request (up to 100).

**Endpoint:** `POST /api/v1/vcons/batch`

**Authentication:** Required

**Request Headers:**

```http
Content-Type: application/json
Authorization: Bearer your-api-key
```

**Request Body:**

Array of vCon objects:

```json
[
  {
    "vcon": "0.4.0",
    "subject": "Call 1",
    "parties": [{"name": "Agent A", "mailto": "a@example.com"}]
  },
  {
    "vcon": "0.4.0",
    "subject": "Call 2",
    "parties": [{"name": "Agent B", "mailto": "b@example.com"}]
  }
]
```

**Response (201 Created - All Successful):**

```json
{
  "success": true,
  "total": 2,
  "created": 2,
  "failed": 0,
  "results": [
    {
      "uuid": "uuid-1",
      "success": true,
      "id": "42"
    },
    {
      "uuid": "uuid-2",
      "success": true,
      "id": "43"
    }
  ],
  "duration_ms": 120
}
```

**Response (207 Multi-Status - Partial Success):**

```json
{
  "success": false,
  "total": 3,
  "created": 2,
  "failed": 1,
  "results": [
    {
      "uuid": "uuid-1",
      "success": true,
      "id": "42"
    },
    {
      "uuid": "uuid-2",
      "success": true,
      "id": "43"
    },
    {
      "uuid": "unknown",
      "success": false,
      "error": "Validation failed: Missing required field: parties"
    }
  ],
  "duration_ms": 150
}
```

**Response (400 Bad Request):**

```json
{
  "error": "Validation Error",
  "message": "Request body must be an array of vCons"
}
```

```json
{
  "error": "Validation Error",
  "message": "Maximum 100 vCons per batch"
}
```

**Example:**

```bash
curl -X POST http://localhost:3000/api/v1/vcons/batch \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-api-key" \
  -d '[
    {"vcon": "0.4.0", "subject": "Call 1", "parties": [{"name": "A", "tel": "+1111"}]},
    {"vcon": "0.4.0", "subject": "Call 2", "parties": [{"name": "B", "tel": "+2222"}]}
  ]'
```

***

### Get vCon

Retrieve a vCon by UUID.

**Endpoint:** `GET /api/v1/vcons/:uuid`

**Authentication:** Required

**URL Parameters:**

| Parameter | Type   | Description          |
| --------- | ------ | -------------------- |
| `uuid`    | string | vCon UUID (required) |

**Response (200 OK):**

```json
{
  "success": true,
  "vcon": {
    "vcon": "0.4.0",
    "uuid": "123e4567-e89b-12d3-a456-426614174000",
    "created_at": "2025-01-02T10:00:00.000Z",
    "subject": "Customer Support Call",
    "parties": [...],
    "dialog": [...],
    "analysis": [...],
    "attachments": [...]
  }
}
```

**Response (404 Not Found):**

```json
{
  "error": "Not Found",
  "message": "vCon with UUID 123e4567-e89b-12d3-a456-426614174000 not found"
}
```

**Example:**

```bash
curl http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000 \
  -H "Authorization: Bearer your-api-key"
```

***

### List vCons

List recent vCons with optional limit.

**Endpoint:** `GET /api/v1/vcons`

**Authentication:** Required

**Query Parameters:**

| Parameter | Type   | Default | Description                          |
| --------- | ------ | ------- | ------------------------------------ |
| `limit`   | number | 10      | Number of vCons to return (max: 100) |

**Response (200 OK):**

```json
{
  "success": true,
  "count": 10,
  "limit": 10,
  "vcons": [
    {
      "vcon": "0.4.0",
      "uuid": "uuid-1",
      "created_at": "2025-01-02T10:00:00.000Z",
      "subject": "Call 1",
      "parties": [...]
    },
    {
      "vcon": "0.4.0",
      "uuid": "uuid-2",
      "created_at": "2025-01-02T09:00:00.000Z",
      "subject": "Call 2",
      "parties": [...]
    }
  ]
}
```

**Example:**

```bash
# Get last 10 vCons (default)
curl http://localhost:3000/api/v1/vcons \
  -H "Authorization: Bearer your-api-key"

# Get last 50 vCons
curl "http://localhost:3000/api/v1/vcons?limit=50" \
  -H "Authorization: Bearer your-api-key"
```

***

### Delete vCon

Delete a vCon by UUID.

**Endpoint:** `DELETE /api/v1/vcons/:uuid`

**Authentication:** Required

**URL Parameters:**

| Parameter | Type   | Description          |
| --------- | ------ | -------------------- |
| `uuid`    | string | vCon UUID (required) |

**Response (200 OK):**

```json
{
  "success": true,
  "message": "vCon 123e4567-e89b-12d3-a456-426614174000 deleted successfully"
}
```

**Response (404 Not Found):**

```json
{
  "error": "Not Found",
  "message": "vCon with UUID 123e4567-e89b-12d3-a456-426614174000 not found"
}
```

**Example:**

```bash
curl -X DELETE http://localhost:3000/api/v1/vcons/123e4567-e89b-12d3-a456-426614174000 \
  -H "Authorization: Bearer your-api-key"
```

***

## Error Handling

All errors follow a consistent format:

```json
{
  "error": "Error Type",
  "message": "Human-readable error description",
  "timestamp": "2025-01-02T10:30:00.000Z"
}
```

### HTTP Status Codes

| Status | Description                               |
| ------ | ----------------------------------------- |
| `200`  | Success                                   |
| `201`  | Created (new vCon)                        |
| `207`  | Multi-Status (batch with partial success) |
| `400`  | Bad Request (validation error)            |
| `401`  | Unauthorized (authentication failed)      |
| `404`  | Not Found                                 |
| `500`  | Internal Server Error                     |
| `503`  | Service Unavailable                       |

### Error Examples

**Internal Server Error (500):**

```json
{
  "error": "Internal Server Error",
  "message": "An unexpected error occurred",
  "timestamp": "2025-01-02T10:30:00.000Z"
}
```

> **Note:** In non-production environments, more detailed error messages are included.

***

## Plugin Integration

The REST API integrates with the vCon MCP Server's plugin system. All vCon operations trigger the appropriate lifecycle hooks:

| Operation         | Hooks Triggered               |
| ----------------- | ----------------------------- |
| Create vCon       | `beforeCreate`, `afterCreate` |
| Get vCon          | `beforeRead`, `afterRead`     |
| Update vCon       | `beforeUpdate`, `afterUpdate` |
| List/Search vCons | `beforeSearch`, `afterSearch` |
| Delete vCon       | `beforeDelete`, `afterDelete` |

This ensures consistent behavior between MCP tools and REST API operations, including:

* Privacy filtering
* Access control
* Audit logging
* Data transformation

See the [Plugin Development Guide](/development/plugins) for more information.

***

## Request Logging

All requests are logged with the following information:

```json
{
  "level": "info",
  "msg": "REST API request",
  "method": "POST",
  "path": "/api/v1/vcons",
  "remote_address": "192.168.1.100",
  "user_agent": "curl/7.79.1"
}
```

Response logging includes duration:

```json
{
  "level": "info",
  "msg": "REST API response",
  "method": "POST",
  "path": "/api/v1/vcons",
  "status": 201,
  "duration_ms": 45
}
```

***

## CORS Configuration

The REST API supports CORS with configurable options:

**Allowed Methods:** `GET`, `POST`, `PUT`, `PATCH`, `DELETE`, `OPTIONS`

**Allowed Headers:** `Content-Type`, `Authorization` (Bearer), `x-api-key` (if `API_KEY_HEADER=x-api-key`)

**Configure CORS Origin:**

```bash
# Allow all origins (default)
CORS_ORIGIN=*

# Allow specific origin
CORS_ORIGIN=https://myapp.com

# Allow multiple origins (comma-separated)
CORS_ORIGIN=https://app1.com,https://app2.com
```

***

## Usage Examples

### JavaScript/Node.js

```javascript
const API_URL = 'http://localhost:3000/api/v1';
const API_KEY = 'your-api-key';

// Create a vCon
async function createVCon(vcon) {
  const response = await fetch(`${API_URL}/vcons`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: JSON.stringify(vcon),
  });
  return response.json();
}

// Get a vCon
async function getVCon(uuid) {
  const response = await fetch(`${API_URL}/vcons/${uuid}`, {
    headers: { 'Authorization': `Bearer ${API_KEY}` },
  });
  return response.json();
}

// Batch create
async function batchCreate(vcons) {
  const response = await fetch(`${API_URL}/vcons/batch`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${API_KEY}`,
    },
    body: JSON.stringify(vcons),
  });
  return response.json();
}

// Example usage
const result = await createVCon({
  vcon: '0.4.0',
  subject: 'Support Call',
  parties: [
    { name: 'Agent', mailto: 'agent@company.com' },
    { name: 'Customer', tel: '+1-555-1234' },
  ],
});

console.log('Created vCon:', result.uuid);
```

### Python

```python
import requests

API_URL = 'http://localhost:3000/api/v1'
API_KEY = 'your-api-key'

headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {API_KEY}',
}

# Create a vCon
def create_vcon(vcon):
    response = requests.post(f'{API_URL}/vcons', json=vcon, headers=headers)
    return response.json()

# Get a vCon
def get_vcon(uuid):
    response = requests.get(f'{API_URL}/vcons/{uuid}', headers=headers)
    return response.json()

# Batch create
def batch_create(vcons):
    response = requests.post(f'{API_URL}/vcons/batch', json=vcons, headers=headers)
    return response.json()

# Example usage
result = create_vcon({
    'vcon': '0.4.0',
    'subject': 'Support Call',
    'parties': [
        {'name': 'Agent', 'mailto': 'agent@company.com'},
        {'name': 'Customer', 'tel': '+1-555-1234'},
    ],
})

print(f"Created vCon: {result['uuid']}")
```

### cURL Examples

```bash
# Health check
curl http://localhost:3000/api/v1/health

# Create vCon
curl -X POST http://localhost:3000/api/v1/vcons \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-key" \
  -d '{"vcon":"0.4.0","subject":"Test","parties":[{"name":"Test","tel":"+1111"}]}'

# Get vCon
curl http://localhost:3000/api/v1/vcons/UUID-HERE \
  -H "Authorization: Bearer your-key"

# List vCons
curl "http://localhost:3000/api/v1/vcons?limit=20" \
  -H "Authorization: Bearer your-key"

# Delete vCon
curl -X DELETE http://localhost:3000/api/v1/vcons/UUID-HERE \
  -H "Authorization: Bearer your-key"

# Batch create
curl -X POST http://localhost:3000/api/v1/vcons/batch \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-key" \
  -d '[{"vcon":"0.4.0","parties":[{"name":"A","tel":"+1"}]},{"vcon":"0.4.0","parties":[{"name":"B","tel":"+2"}]}]'
```

***

## Full Endpoint Reference

The REST API now has full parity with MCP tools. All endpoints use `/api/v1` as the default base path.

### vCon CRUD & Sub-resources

| Method | Path                       | Description                                                                                     |
| ------ | -------------------------- | ----------------------------------------------------------------------------------------------- |
| POST   | `/vcons`                   | Create a vCon                                                                                   |
| POST   | `/vcons/batch`             | Batch create (up to 100)                                                                        |
| GET    | `/vcons`                   | List/search vCons (filter with query params)                                                    |
| GET    | `/vcons/:uuid`             | Get vCon by UUID (`?format=full\|summary\|metadata`)                                            |
| GET    | `/vcons/:uuid/analysis`    | Read analysis, optionally filtered by `?type=`                                                  |
| GET    | `/vcons/:uuid/attachments` | Read attachments, preferably filtered by `?purpose=`; `?type=` remains for legacy compatibility |
| PATCH  | `/vcons/:uuid`             | Update vCon metadata (subject, extensions, critical)                                            |
| DELETE | `/vcons/:uuid`             | Delete a vCon                                                                                   |
| POST   | `/vcons/:uuid/dialog`      | Add dialog to a vCon                                                                            |
| POST   | `/vcons/:uuid/analysis`    | Add analysis to a vCon                                                                          |
| POST   | `/vcons/:uuid/attachments` | Add attachment to a vCon                                                                        |

### Discovery

| Method | Path                              | Description                                                                 |
| ------ | --------------------------------- | --------------------------------------------------------------------------- |
| GET    | `/discovery/attachments/purposes` | Discover live attachment purposes (`?include_counts=false`, `?min_count=2`) |
| GET    | `/discovery/attachments/types`    | Discover legacy attachment types (`?include_counts=false`, `?min_count=2`)  |
| GET    | `/discovery/analysis/types`       | Discover live analysis types (`?include_counts=false`, `?min_count=2`)      |

### Tags

| Method | Path                     | Description                                    |
| ------ | ------------------------ | ---------------------------------------------- |
| GET    | `/vcons/:uuid/tags`      | Get all tags (or single via `?key=`)           |
| PUT    | `/vcons/:uuid/tags/:key` | Set a tag (body: `{"value": "..."}`)           |
| DELETE | `/vcons/:uuid/tags/:key` | Remove a tag                                   |
| DELETE | `/vcons/:uuid/tags`      | Remove all tags                                |
| GET    | `/tags`                  | Discover unique tags across DB                 |
| GET    | `/tags/search`           | Search vCons by tags (`?tags={"key":"value"}`) |

### Search

| Method | Path                     | Description                                |
| ------ | ------------------------ | ------------------------------------------ |
| GET    | `/vcons/search/content`  | Keyword/full-text search (`?q=`)           |
| GET    | `/vcons/search/semantic` | Semantic/embedding search (`?q=`)          |
| GET    | `/vcons/search/hybrid`   | Combined keyword + semantic search (`?q=`) |

### Database & Analytics

| Method | Path                     | Description                   |
| ------ | ------------------------ | ----------------------------- |
| GET    | `/database/shape`        | Database schema shape         |
| GET    | `/database/stats`        | Performance statistics        |
| GET    | `/database/size`         | Size info and recommendations |
| GET    | `/database/health`       | Health metrics                |
| POST   | `/database/analyze`      | Analyze a SQL query plan      |
| GET    | `/analytics`             | Full analytics dashboard      |
| GET    | `/analytics/growth`      | Growth trends                 |
| GET    | `/analytics/content`     | Content analytics             |
| GET    | `/analytics/tags`        | Tag analytics                 |
| GET    | `/analytics/attachments` | Attachment analytics          |

### Infrastructure

| Method | Path              | Description                |
| ------ | ----------------- | -------------------------- |
| GET    | `/health`         | Health check (no auth)     |
| GET    | `/version`        | Version info (no auth)     |
| GET    | `/schema`         | vCon JSON Schema (no auth) |
| GET    | `/examples/:type` | Example vCons (no auth)    |

***

## Comparison: REST API vs MCP Tools

| Feature    | REST API                                  | MCP Tools               |
| ---------- | ----------------------------------------- | ----------------------- |
| Protocol   | HTTP/JSON                                 | MCP (stdio/HTTP)        |
| Auth       | API Key (Bearer)                          | MCP client auth         |
| Best for   | External integrations, scripts            | AI assistants           |
| Operations | Full CRUD + sub-resources                 | Full toolkit (46 tools) |
| Search     | 4 modes (list, keyword, semantic, hybrid) | 4 search modes          |
| Tags       | Full tag management                       | Full tag management     |
| Analytics  | Full analytics suite                      | Full analytics suite    |
| Batch      | Yes (100 max)                             | No                      |
| Streaming  | No                                        | Yes (SSE)               |

Both interfaces share the same `VConService` business logic layer, plugin hooks, and database queries. Choose based on your integration pattern.

***

## Next Steps

* See [MCP Tools](/api-reference/tools) for the full MCP toolkit
* See [Resources](/api-reference/resources) for URI-based access
* See [Docker Deployment](/deployment/docker) for production setup
* See [Plugin Development](/development/plugins) for extending the API


# MCP Tools

Complete reference for all Model Context Protocol (MCP) tools provided by the vCon MCP Server.

## Overview

The vCon MCP Server provides 46 tools organized into these functional groups:

* [**Redesigned Contract Tools**](#redesigned-contract-tools) - Recommended discovery, fetch, search, and aggregation surface for new clients
* [**Core Operations**](#core-operations) - Create, read, update, delete vCons
* [**Component Management**](#component-management) - Add, update, and remove parties, dialog, analysis, attachments
* [**Search & Query**](#search--query) - Four search modes with different capabilities
* [**Tag Management**](#tag-management) - Organize with key-value metadata
* [**Database Tools**](#database-tools) - Inspect and optimize database
* [**Database Analytics**](#database-analytics) - Comprehensive database analytics and insights
* [**Database Size Tools**](#database-size-tools) - Smart limits and size awareness for large databases
* [**Schema & Examples**](#schema--examples) - Get schemas and example vCons

## Recommended Starting Point

If you are building a new client, especially an LLM-generated one, start with the redesigned additive tool family:

* `vcon_capabilities`
* `vcon_taxonomy`
* `vcon_search`
* `vcon_fetch`
* `describe_response_shape`

These tools were added to address undocumented limits, inconsistent envelopes, and hard-to-predict payloads in the older tool set.

## Are The Older Tools Still Useful?

Yes. The older tools are still useful for backward compatibility, narrow workflows, and incremental migration. Existing clients built around `get_vcon`, `search_vcons`, `search_vcons_content`, `search_vcons_semantic`, `search_vcons_hybrid`, and `search_by_tags` can keep working while new clients adopt the redesigned surface.

For new client work, prefer the redesigned tools first. Treat the older tools as compatibility and specialized interfaces rather than the default entry point.

***

## Tool Categories

Tools are organized into **5 categories** that can be enabled or disabled for different deployment scenarios. By default, all categories are enabled.

| Category    | Tools                                                                                                                                                                                                                                             | Description             |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- |
| `read`      | `get_vcon`, `vcon_fetch`, `vcon_capabilities`, `vcon_search`, `vcon_taxonomy`, `describe_response_shape`, `search_vcons`, `search_vcons_content`, `search_vcons_semantic`, `search_vcons_hybrid`, `get_tags`, `search_by_tags`, `get_unique_tags` | All read operations     |
| `write`     | `create_vcon`, `update_vcon`, `delete_vcon`, `add_analysis`, `add_dialog`, `add_attachment`, `create_vcon_from_template`, `manage_tag`, `remove_all_tags`                                                                                         | All mutating operations |
| `schema`    | `get_schema`, `get_examples`                                                                                                                                                                                                                      | Documentation helpers   |
| `analytics` | `get_database_analytics`, `get_monthly_growth_analytics`, `get_attachment_analytics`, `get_tag_analytics`, `get_content_analytics`, `get_database_health_metrics`                                                                                 | Business intelligence   |
| `infra`     | `get_database_shape`, `get_database_stats`, `analyze_query`, `get_database_size_info`, `get_smart_search_limits`                                                                                                                                  | Admin/debugging         |

### Enabling/Disabling Categories

Configure via environment variables:

```bash
# Use a preset profile
MCP_TOOLS_PROFILE=readonly   # Options: full, readonly, user, admin, minimal, public

# Or enable specific categories only
MCP_ENABLED_CATEGORIES=read,write,schema

# Or disable specific categories (starts with all enabled)
MCP_DISABLED_CATEGORIES=analytics,infra

# Disable individual tools
MCP_DISABLED_TOOLS=delete_vcon,analyze_query
```

### Deployment Profiles

| Profile    | Categories                                               | Use Case                                     |
| ---------- | -------------------------------------------------------- | -------------------------------------------- |
| `full`     | All                                                      | Development, full access                     |
| `readonly` | read, schema                                             | Read-only deployments                        |
| `user`     | read, write, schema                                      | End-user facing                              |
| `admin`    | read, analytics, infra, schema                           | Admin dashboards                             |
| `minimal`  | read, write                                              | Basic CRUD only                              |
| `public`   | read, schema, minus `vcon_aggregate` and `vcon_taxonomy` | Hosted public datasets; also filters prompts |

The `public` profile is for hosted, read-only datasets where an agent with no prior context connects and has to work out what the corpus is about from `tools/list` alone. It keeps the read and search tools, `get_schema`, `get_examples`, and tag discovery, and hides database internals, analytics, and the two deployment-shaped tools (`vcon_aggregate`, `vcon_taxonomy`). Prompts carry the same categories, so the profile also drops `daily_activity_report`. `MCP_DISABLED_TOOLS` still applies on top of any profile.

See the [Configuration Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/configuration.md) for more details.

## Redesigned Contract Tools

These tools are additive. They do not replace the legacy tools immediately, but they are the recommended surface for new client development.

### vcon\_capabilities

Discover supported include groups, search modes, cursor semantics, byte-budget defaults, and migration hints before building a client.

**Use first when:**

* You need to inspect limits before making calls
* You are generating a client from tool descriptions
* You want to know which include groups and search modes are supported

### vcon\_taxonomy

Return dataset-specific guidance, including the portal taxonomy and preferred data sources.

**Important dataset hints surfaced by this tool:**

* Use `tags.portal` values like `negative_experience`, `dnc_request`, and `bad_call_quality` before semantic search for "bad call" or upset-customer views
* Prefer `attachment:strolid_dealer` over sparse `dealer_name` tags for dealer-aware interfaces

### vcon\_search

Unified metadata, keyword, semantic, and hybrid search with one stable response shape:

```json
{
  "ok": true,
  "items": [...],
  "page": {
    "count": 25,
    "total": 187,
    "next_cursor": "..."
  }
}
```

**Highlights:**

* `mode`: `metadata`, `keyword`, `semantic`, or `hybrid`
* `include`: explicit field groups such as `core`, `summary`, `dealer`, `tags`
* cursor pagination via `page.next_cursor`
* explicit response budgeting with `max_response_bytes`
* loud failure with `RESPONSE_TOO_LARGE` instead of silent truncation

### vcon\_fetch

Single-record fetch with one stable response shape:

```json
{
  "ok": true,
  "item": {
    "id": "...",
    "summary": [...],
    "dealer": {...}
  }
}
```

**Highlights:**

* explicit `include` groups instead of `response_format`
* normalized primary identifier field: `id`
* useful lightweight pattern: `include=["core","summary","dealer"]`
* explicit response budgeting with `max_response_bytes`

### describe\_response\_shape

Return the published JSON schema plus one concrete example for redesigned and legacy tools. Use this when a client needs to probe actual envelope structure before wiring a parser.

***

### vcon\_aggregate

Server-side rollup for rate-style questions: which groups have the highest share of vCons matching a tag filter. Groups vCons by an attachment-derived key (this release: the `strolid_dealer` attachment id, where a deployment stores one) and returns `filtered_count` (rows matching the supplied tags) and `baseline_count` (all rows in the group), so a client can divide for a rate in one round trip. Requires the Postgres RPC `aggregate_vcons_by_dealer_stats` from the latest migration.

***

### vcon\_graph\_shape

Return the default OSS vCon shape graph for the corpus: nodes for analysis types, attachment purposes, legacy attachment types (when purpose is absent), and tag keys, plus optional co-occurrence edges between analysis types and attachment purposes. Spec-generic structure only, no business ontology. Returns the same payload as the resource `vcon://v1/graph/shape`; prefer the resource when the client supports resources.

***

## Core Operations

### create\_vcon

Create a new vCon (Virtual Conversation) record.

**Input Parameters:**

```typescript
{
  vcon_data: {
    vcon: "0.4.0",           // vCon version
    uuid?: string,           // Auto-generated if not provided
    subject?: string,        // Conversation subject
    parties: Party[],        // At least one party required
    dialog?: Dialog[],       // Optional conversation content
    analysis?: Analysis[],   // Optional AI analysis
    attachments?: Attachment[], // Optional files
    extensions?: string[],   // Optional extensions
    critical?: string[]      // Optional: extensions that must be supported (v0.4.0)
  },
  metadata?: {
    basename?: string,
    filename?: string,
    tags?: object
  },
  validate_before_insert?: boolean  // Default: true
}
```

**Response:**

```typescript
{
  success: boolean,
  uuid: string,           // UUID of created vCon
  vcon?: object          // Full vCon if requested
}
```

**Example:**

```typescript
{
  "vcon_data": {
    "vcon": "0.4.0",
    "subject": "Customer Support Call",
    "parties": [
      {
        "name": "Agent Smith",
        "mailto": "smith@company.com",
        "role": "agent"
      },
      {
        "name": "John Doe",
        "tel": "+1-555-1234",
        "role": "customer"
      }
    ]
  }
}
```

***

### get\_vcon

Retrieve a vCon by UUID.

**Input Parameters:**

```typescript
{
  uuid: string,              // vCon UUID (required)
  include_components?: string[], // ["parties", "dialog", "analysis", "attachments", "all"]
  include_metadata?: boolean  // Default: true
}
```

**Response:**

```typescript
{
  success: boolean,
  vcon: {
    vcon: "0.4.0",
    uuid: string,
    created_at: string,
    updated_at?: string,
    subject?: string,
    parties: Party[],
    dialog?: Dialog[],
    analysis?: Analysis[],
    attachments?: Attachment[]
  }
}
```

**Example:**

```typescript
{
  "uuid": "123e4567-e89b-12d3-a456-426614174000"
}
```

***

### update\_vcon

Update vCon metadata and top-level fields.

**Input Parameters:**

```typescript
{
  uuid: string,           // vCon UUID (required)
  updates: {
    subject?: string,
    extensions?: string[],
    critical?: string[],
    [key: string]: any
  },
  merge_strategy?: "replace" | "merge" | "append",  // Default: "merge"
  validate_after_update?: boolean  // Default: true
}
```

**Response:**

```typescript
{
  success: boolean,
  message: string,
  updated_vcon?: object
}
```

**Example:**

```typescript
{
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "updates": {
    "subject": "Updated: Customer Support Call - Resolved"
  }
}
```

***

### delete\_vcon

Delete a vCon and all related data.

**Input Parameters:**

```typescript
{
  uuid: string,           // vCon UUID (required)
  confirm: boolean,       // Must be true (safety check)
  cascade_delete?: boolean  // Default: true (deletes all components)
}
```

**Response:**

```typescript
{
  success: boolean,
  message: string,
  deleted_uuid: string
}
```

**Example:**

```typescript
{
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "confirm": true
}
```

***

### create\_vcon\_from\_template

Create a vCon from a predefined template.

**Input Parameters:**

```typescript
{
  template_name: "phone_call" | "chat_conversation" | "email_thread" | "video_meeting" | "custom",
  subject?: string,
  parties: Party[],      // At least 2 parties required
  metadata?: object,
  template_params?: object  // Template-specific parameters
}
```

**Templates Available:**

* **phone\_call** - Phone conversation with duration tracking
* **chat\_conversation** - Text-based chat with timestamps
* **email\_thread** - Email chain with threading
* **video\_meeting** - Video conference with participants
* **custom** - Blank template with custom fields

**Response:**

```typescript
{
  success: boolean,
  uuid: string,
  vcon: object
}
```

**Example:**

```typescript
{
  "template_name": "phone_call",
  "subject": "Sales Call",
  "parties": [
    { "name": "Sales Rep", "mailto": "rep@company.com" },
    { "name": "Prospect", "mailto": "prospect@client.com" }
  ]
}
```

***

## Component Management

### add\_dialog

Add a dialog entry (conversation segment) to a vCon.

**Input Parameters:**

```typescript
{
  vcon_uuid: string,      // vCon UUID (required)
  dialog: {
    type: "recording" | "text" | "transfer" | "incomplete",  // Required
    start?: string,       // ISO 8601 timestamp
    duration?: number,    // Duration in seconds
    parties?: number[],   // Array of party indices
    originator?: number,  // Party index of originator
    mediatype?: string,   // MIME type
    filename?: string,
    body?: string,        // Dialog content
    encoding?: "none" | "base64url" | "json",
    url?: string,         // External URL
    session_id?: string,
    application?: string,
    message_id?: string
  }
}
```

**Response:**

```typescript
{
  success: boolean,
  message: string,
  dialog_index: number
}
```

**Example:**

```typescript
{
  "vcon_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "dialog": {
    "type": "text",
    "start": "2025-10-14T10:30:00Z",
    "parties": [0, 1],
    "originator": 1,
    "body": "Hello, I need help with my account.",
    "encoding": "none"
  }
}
```

***

### add\_analysis

Add AI/ML analysis results to a vCon.

**Input Parameters:**

```typescript
{
  vcon_uuid: string,      // vCon UUID (required)
  analysis: {
    type: string,         // Analysis type (e.g., "sentiment", "summary")
    dialog?: number | number[],  // Associated dialog indices
    vendor: string,       // REQUIRED - Analysis vendor
    product?: string,     // Product/model name
    schema?: string,      // Schema version
    body?: string,        // Analysis content
    encoding?: "none" | "json" | "base64url",
    url?: string,
    mediatype?: string
  }
}
```

**Common Analysis Types:**

* `sentiment` - Sentiment analysis
* `summary` - Conversation summary
* `transcript` - Transcription
* `translation` - Translation
* `keywords` - Keyword extraction
* `entities` - Named entity recognition
* `topics` - Topic classification
* `action_items` - Action item extraction

**Response:**

```typescript
{
  success: boolean,
  message: string,
  analysis_index: number
}
```

**Example:**

```typescript
{
  "vcon_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "analysis": {
    "type": "sentiment",
    "vendor": "OpenAI",
    "product": "GPT-4",
    "schema": "v1.0",
    "body": "{\"sentiment\": \"positive\", \"score\": 0.85, \"confidence\": 0.92}",
    "encoding": "json",
    "dialog": [0]
  }
}
```

***

### add\_attachment

Add an attachment (file, document, etc.) to a vCon.

**Input Parameters:**

```typescript
{
  vcon_uuid: string,      // vCon UUID (required)
  attachment: {
    type: string,         // Attachment type
    start?: string,       // ISO 8601 timestamp
    party?: number,       // Associated party index
    dialog?: number,      // Associated dialog index
    mediatype?: string,   // MIME type
    filename?: string,
    body?: string,        // Attachment content
    encoding?: "none" | "base64url" | "json",
    url?: string         // External URL
  }
}
```

**Response:**

```typescript
{
  success: boolean,
  message: string,
  attachment_index: number
}
```

**Example:**

```typescript
{
  "vcon_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "attachment": {
    "type": "invoice",
    "mediatype": "application/pdf",
    "filename": "invoice-12345.pdf",
    "body": "base64-encoded-pdf-content",
    "encoding": "base64url"
  }
}
```

***

### add\_party

Append a party to an existing vCon.

```typescript
{
  vcon_uuid: string,   // required
  party: {             // any subset of party fields (name, tel, sip, mailto, role, uuid, did, ...)
    name?: string,
    tel?: string,
    mailto?: string,
    role?: string
  }
}
// Response: { success, message, party_index }
```

***

### Sub-resource Updates & Removal

Index-addressed edits to a vCon's child arrays. Each tool takes `vcon_uuid` plus an integer `index` (the element's position in its array). **Update** tools use PUT semantics: omitted fields are cleared. **Removal** follows IETF core-02 §4.1.8: party and dialog removals preserve the slot as a placeholder so positional references (`dialog.parties`, `attachment.party`, `analysis.dialog`, etc.) do not shift; analysis and attachment removals hard-delete the element and renumber the rest.

| Tool                | Parameters                         | Behavior                                                                                 |
| ------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------- |
| `update_party`      | `vcon_uuid`, `index`, `party`      | Replace the party at `index`                                                             |
| `remove_party`      | `vcon_uuid`, `index`, `anonymize?` | Remove party; leaves an empty placeholder, or `{name:"anonymous"}` when `anonymize=true` |
| `update_dialog`     | `vcon_uuid`, `index`, `dialog`     | Replace the dialog at `index`                                                            |
| `remove_dialog`     | `vcon_uuid`, `index`               | Remove dialog; leaves a content-stripped placeholder that keeps `type`                   |
| `update_analysis`   | `vcon_uuid`, `index`, `analysis`   | Replace the analysis at `index` (`vendor` required)                                      |
| `remove_analysis`   | `vcon_uuid`, `index`               | Hard-delete; remaining analyses renumbered contiguously                                  |
| `update_attachment` | `vcon_uuid`, `index`, `attachment` | Replace the attachment at `index`                                                        |
| `remove_attachment` | `vcon_uuid`, `index`               | Hard-delete and renumber; removing a `tags` attachment clears the vCon's tags            |

Each returns `{ success, message }`.

***

## Search & Query

### search\_vcons

Basic search with filtering by metadata (subject, parties, dates).

**Input Parameters:**

```typescript
{
  subject?: string,       // Subject text search
  party_name?: string,    // Party name search
  party_email?: string,   // Party email search
  party_tel?: string,     // Party phone search
  start_date?: string,    // ISO 8601 date
  end_date?: string,      // ISO 8601 date
  limit?: number,         // Default: 50, Max: 1000
  offset?: number         // For pagination
}
```

**Response:**

```typescript
{
  success: boolean,
  count: number,
  vcons: VCon[],
  has_more: boolean
}
```

**Example:**

```typescript
{
  "subject": "support",
  "start_date": "2025-10-01T00:00:00Z",
  "limit": 20
}
```

***

### search\_vcons\_content

Full-text keyword search across dialog, analysis, and party content.

**Input Parameters:**

```typescript
{
  query: string,          // Search query (required)
  tags?: object,          // Tag filters
  start_date?: string,
  end_date?: string,
  limit?: number,         // Default: 50
  include_snippets?: boolean  // Default: true
}
```

**Response:**

```typescript
{
  success: boolean,
  count: number,
  results: [{
    vcon_id: string,
    content_type: "subject" | "dialog" | "analysis" | "party",
    content_index?: number,
    relevance_score: number,
    snippet?: string,     // Highlighted match
    vcon?: object
  }]
}
```

**Example:**

```typescript
{
  "query": "billing issue refund",
  "tags": { "department": "support" },
  "limit": 25
}
```

***

### search\_vcons\_semantic

AI-powered semantic search using embeddings.

**Input Parameters:**

```typescript
{
  query?: string,         // Natural language query
  embedding?: number[],   // Or provide embedding directly (384 dims)
  threshold?: number,     // Similarity threshold (0-1), default: 0.7
  tags?: object,          // Tag filters
  limit?: number          // Default: 20
}
```

**Response:**

```typescript
{
  success: boolean,
  count: number,
  results: [{
    vcon_id: string,
    similarity_score: number,
    matched_content: {
      subject?: string,
      dialog_excerpts?: Array<{
        dialog_index: number,
        text: string,
        relevance: number
      }>
    },
    vcon?: object
  }]
}
```

**Example:**

```typescript
{
  "query": "customer frustrated about late delivery",
  "threshold": 0.75,
  "tags": { "priority": "high" },
  "limit": 15
}
```

***

### search\_vcons\_hybrid

Combined keyword + semantic search for comprehensive results.

**Input Parameters:**

```typescript
{
  query: string,          // Search query (required)
  semantic_weight?: number,  // 0-1, default: 0.6 (60% semantic, 40% keyword)
  tags?: object,
  start_date?: string,
  end_date?: string,
  limit?: number          // Default: 30
}
```

**Response:**

```typescript
{
  success: boolean,
  count: number,
  results: [{
    vcon_id: string,
    combined_score: number,
    keyword_score: number,
    semantic_score: number,
    vcon?: object
  }]
}
```

**Example:**

```typescript
{
  "query": "pricing discussion discount",
  "semantic_weight": 0.5,
  "tags": { "department": "sales" },
  "limit": 20
}
```

***

## Tag Management

The tag toolset was consolidated to 5 tools. Tags are stored as a special vCon attachment (`type: "tags"`, `encoding: "json"`, body is a JSON array of `"key:value"` strings).

### manage\_tag

Add, update, or remove a single tag on a vCon. Replaces the older `add_tag`, `update_tags`, and `remove_tag` tools.

**Input Parameters:**

```typescript
{
  vcon_uuid: string,                       // vCon UUID (required)
  action: "set" | "remove",                // (required)
  key: string,                             // Tag key (required)
  value?: string | number | boolean        // Required when action="set"
}
```

**Response (on success):**

```typescript
{
  success: true,
  message: string,
  action: "set" | "remove",
  key: string,
  value?: string                            // Stringified, only when action="set"
}
```

**Examples:**

```typescript
// Set a tag
{
  "vcon_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "action": "set",
  "key": "department",
  "value": "sales"
}

// Remove a tag
{
  "vcon_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "action": "remove",
  "key": "department"
}
```

***

### get\_tags

Retrieve tags from a vCon. Provide a specific `key` to get one tag, or omit `key` to get all tags. Replaces the older `get_tag` and `get_all_tags` tools.

**Input Parameters:**

```typescript
{
  vcon_uuid: string,                                       // (required)
  key?: string,                                            // Omit for all tags
  default_value?: string | number | boolean | null         // Used when key is provided
}
```

**Response — single tag (key provided):**

```typescript
{
  success: true,
  key: string,
  value: string | number | boolean | null,
  exists: boolean
}
```

**Response — all tags (key omitted):**

```typescript
{
  success: true,
  vcon_uuid: string,
  tags: { [key: string]: string },
  count: number
}
```

**Example Response (all tags):**

```json
{
  "success": true,
  "vcon_uuid": "123e4567-e89b-12d3-a456-426614174000",
  "tags": {
    "department": "sales",
    "priority": "high",
    "status": "open",
    "customer_id": "CUST-12345"
  },
  "count": 4
}
```

***

### remove\_all\_tags

Remove all tags from a vCon.

**Input Parameters:**

```typescript
{
  vcon_uuid: string                       // (required)
}
```

***

### search\_by\_tags

Find vCons by tag criteria. All specified tags must match (AND logic).

**Input Parameters:**

```typescript
{
  tags: { [key: string]: string },        // Non-empty object (required)
  limit?: number,                          // Default: 50, Max: 100
  return_full_vcons?: boolean,             // Default: false for >20 results, true otherwise
  max_full_vcons?: number                  // Default: 20, Max: 50
}
```

**Response:**

```typescript
{
  success: true,
  count: number,
  tags_searched: object,
  vcon_uuids: string[],                    // All matching UUIDs (up to limit)
  vcons?: VCon[],                          // Only when return_full_vcons=true
  message?: string                          // Hint about result size
}
```

**Behavior:**

* Always returns `vcon_uuids` for matching vCons (up to `limit`).
* For result sets > 20, only UUIDs are returned by default to keep the response under MCP size limits.
* Set `return_full_vcons: true` to receive full vCon objects (capped at `max_full_vcons`).
* The `tags` parameter must be a non-empty object; null, undefined, or `{}` is rejected.

**Example:**

```typescript
{
  "tags": {
    "department": "support",
    "priority": "high",
    "status": "open"
  },
  "limit": 25
}
```

***

### get\_unique\_tags

Discover all unique tag keys and values across the database. Useful for building selection UIs and tag analytics.

**Input Parameters:**

```typescript
{
  include_counts?: boolean,                // Include usage counts; default false
  key_filter?: string,                     // Case-insensitive substring match on keys
  min_count?: number                       // Minimum occurrence; default 1
}
```

**Response:**

```typescript
{
  success: true,
  unique_keys: string[],
  unique_key_count: number,
  tags_by_key: {
    [key: string]: string[]                // All distinct values per key
  },
  counts_per_value?: {                     // Only when include_counts=true
    [key: string]: { [value: string]: number }
  },
  total_vcons_with_tags: number
}
```

**Example:**

```typescript
{
  "include_counts": true,
  "key_filter": "department"
}
```

***

## Database Tools

### get\_database\_shape

Get database structure, sizes, and indexes.

**Input Parameters:**

```typescript
{
  include_counts?: boolean,   // Default: true
  include_sizes?: boolean,    // Default: true
  include_indexes?: boolean,  // Default: true
  include_columns?: boolean   // Default: false
}
```

**Response:**

```typescript
{
  success: boolean,
  database_shape: {
    timestamp: string,
    tables: [{
      name: string,
      schema: string,
      row_count: number,
      total_size: string,
      table_size: string,
      indexes_size: string,
      indexes?: Array<{
        indexname: string,
        index_type: string,
        index_size: string
      }>,
      columns?: Array<{
        column_name: string,
        data_type: string,
        is_nullable: string
      }>
    }],
    relationships: Array<{
      from_table: string,
      from_column: string,
      to_table: string,
      to_column: string
    }>
  }
}
```

***

### get\_database\_stats

Get performance metrics and usage statistics.

**Input Parameters:**

```typescript
{
  include_query_stats?: boolean,   // Default: true
  include_index_usage?: boolean,   // Default: true
  include_cache_stats?: boolean,   // Default: true
  table_name?: string               // Specific table
}
```

**Response:**

```typescript
{
  success: boolean,
  database_stats: {
    timestamp: string,
    cache_stats: {
      hit_ratio: string,
      heap_blocks_hit: number,
      heap_blocks_read: number
    },
    table_stats: Array<{
      table_name: string,
      sequential_scans: number,
      index_scans: number,
      inserts: number,
      updates: number,
      deletes: number,
      live_rows: number,
      dead_rows: number
    }>,
    index_usage: Array<{
      table_name: string,
      index_name: string,
      scans: number,
      rows_read: number
    }>,
    unused_indexes: Array<{
      table_name: string,
      index_name: string,
      index_size: string
    }>
  }
}
```

***

### analyze\_query

Analyze SQL query execution plan (limited support).

**Input Parameters:**

```typescript
{
  query: string,          // SELECT query (required)
  analyze_mode?: "explain" | "explain_analyze"  // Default: "explain"
}
```

**Note:** Has limited support due to RPC constraints. Use direct database access for full EXPLAIN capabilities.

***

## Database Analytics

### get\_database\_analytics

Get comprehensive database analytics including size, growth trends, content distribution, and health metrics.

**Input Parameters:**

```typescript
{
  include_growth_trends?: boolean,      // Include monthly growth trends (default: true)
  include_content_analytics?: boolean,  // Include content analysis (default: true)
  include_attachment_stats?: boolean,   // Include attachment statistics (default: true)
  include_tag_analytics?: boolean,      // Include tag usage patterns (default: true)
  include_health_metrics?: boolean,     // Include health metrics (default: true)
  months_back?: number                  // Months to analyze (default: 12)
}
```

**Response:**

```typescript
{
  success: true,
  database_analytics: {
    timestamp: string,
    summary: {
      total_vcons: number,
      total_parties: number,
      total_dialogs: number,
      total_analysis: number,
      total_attachments: number,
      total_size_bytes: number,
      total_size_pretty: string,
      database_health_score: number
    },
    tables: {
      [table_name]: {
        row_count: number,
        total_size: string,
        table_size: string
      }
    },
    growth: {
      monthly_data: Array<{
        month: string,
        vcon_count: number,
        total_size: number
      }>,
      summary: {
        total_growth: number,
        avg_monthly_growth: number,
        growth_percentage: number
      }
    },
    content: {
      dialog_types: Array<{
        type: string,
        count: number,
        avg_duration: number
      }>,
      analysis_types: Array<{
        type: string,
        vendor: string,
        count: number
      }>,
      party_roles: Array<{
        role: string,
        count: number,
        unique_names: number
      }>
    },
    attachments: {
      type_breakdown: Array<{
        type: string,
        count: number,
        total_size: number,
        percentage: number
      }>,
      size_distribution: Array<{
        size_bucket: string,
        count: number,
        percentage: number
      }>
    },
    tags: {
      tag_frequency: Array<{
        key: string,
        usage_count: number,
        unique_values: number
      }>,
      value_distribution: Array<{
        key: string,
        value: string,
        count: number,
        percentage: number
      }>
    },
    health: {
      table_performance: Array<{
        table_name: string,
        sequential_scans: number,
        index_scans: number,
        dead_row_percentage: number
      }>,
      index_usage: Array<{
        table_name: string,
        index_name: string,
        scans: number,
        health_status: string
      }>
    }
  }
}
```

**Example:**

```typescript
{
  "include_growth_trends": true,
  "include_content_analytics": true,
  "months_back": 6
}
```

***

### get\_monthly\_growth\_analytics

Get detailed monthly growth analytics with trends and projections.

**Input Parameters:**

```typescript
{
  months_back?: number,           // Months to analyze (default: 12)
  include_projections?: boolean,  // Include growth projections (default: true)
  granularity?: 'monthly' | 'weekly' | 'daily'  // Time granularity (default: 'monthly')
}
```

**Response:**

```typescript
{
  success: true,
  monthly_growth_analytics: {
    timestamp: string,
    period: string,
    granularity: string,
    trends: {
      vcon_creation: Array<{
        period: string,
        vcon_count: number,
        unique_vcons: number
      }>,
      size_growth: Array<{
        period: string,
        dialog_size: number,
        attachment_size: number,
        total_size: number
      }>,
      content_volume: Array<{
        period: string,
        vcon_count: number,
        dialog_count: number,
        analysis_count: number,
        attachment_count: number
      }>
    },
    growth_rates: {
      vcon_growth_rate: number,
      size_growth_rate: number
    },
    projections: {
      next_3_months: {
        projected_vcons: number,
        projected_size: number,
        projected_size_pretty: string
      },
      growth_rates: {
        vcon_growth_rate: number,
        size_growth_rate: number
      }
    }
  }
}
```

***

### get\_attachment\_analytics

Get comprehensive attachment analytics including file type distribution and size analysis.

**Input Parameters:**

```typescript
{
  include_size_distribution?: boolean,  // Include size distribution (default: true)
  include_type_breakdown?: boolean,     // Include file type breakdown (default: true)
  include_temporal_patterns?: boolean,  // Include temporal patterns (default: false)
  top_n_types?: number                  // Top N file types to analyze (default: 10)
}
```

**Response:**

```typescript
{
  success: true,
  attachment_analytics: {
    timestamp: string,
    summary: {
      total_attachments: number,
      total_size: number,
      avg_size: number,
      unique_types: number,
      vcons_with_attachments: number
    },
    type_breakdown: Array<{
      type: string,
      count: number,
      total_size: number,
      avg_size: number,
      percentage: number
    }>,
    size_distribution: Array<{
      size_bucket: string,
      count: number,
      total_size: number,
      percentage: number
    }>,
    temporal_patterns: Array<{
      month: string,
      attachment_count: number,
      total_size: number,
      avg_size: number
    }>
  }
}
```

***

### get\_tag\_analytics

Get comprehensive tag analytics including usage patterns and value distribution.

**Input Parameters:**

```typescript
{
  include_frequency_analysis?: boolean,  // Include frequency analysis (default: true)
  include_value_distribution?: boolean,  // Include value distribution (default: true)
  include_temporal_trends?: boolean,     // Include temporal trends (default: false)
  top_n_keys?: number,                   // Top N tag keys to analyze (default: 20)
  min_usage_count?: number               // Minimum usage count filter (default: 1)
}
```

**Response:**

```typescript
{
  success: true,
  tag_analytics: {
    timestamp: string,
    summary: {
      unique_keys: number,
      unique_values: number,
      vcons_with_tags: number,
      total_tag_assignments: number
    },
    frequency_analysis: Array<{
      key: string,
      usage_count: number,
      unique_values: number,
      vcons_with_tag: number,
      avg_values_per_key: number
    }>,
    value_distribution: Array<{
      key: string,
      value: string,
      count: number,
      percentage: number
    }>,
    temporal_trends: Array<{
      month: string,
      key: string,
      usage_count: number
    }>
  }
}
```

***

### get\_content\_analytics

Get comprehensive content analytics including dialog types, analysis breakdown, and conversation metrics.

**Input Parameters:**

```typescript
{
  include_dialog_analysis?: boolean,     // Include dialog analysis (default: true)
  include_analysis_breakdown?: boolean,  // Include analysis breakdown (default: true)
  include_party_patterns?: boolean,      // Include party patterns (default: true)
  include_conversation_metrics?: boolean, // Include conversation metrics (default: true)
  include_temporal_content?: boolean     // Include temporal content patterns (default: false)
}
```

**Response:**

```typescript
{
  success: true,
  content_analytics: {
    timestamp: string,
    summary: {
      total_vcons: number,
      total_parties: number,
      total_dialogs: number,
      total_analysis: number,
      total_attachments: number,
      total_duration_seconds: number,
      avg_duration_seconds: number
    },
    dialog_analysis: Array<{
      type: string,
      count: number,
      avg_duration: number,
      total_duration: number,
      total_size: number,
      unique_vcons: number
    }>,
    analysis_breakdown: Array<{
      type: string,
      vendor: string,
      count: number,
      avg_confidence: number,
      unique_vcons: number
    }>,
    party_patterns: Array<{
      role: string,
      count: number,
      unique_names: number,
      unique_emails: number,
      unique_phones: number,
      unique_vcons: number
    }>,
    conversation_metrics: {
      total_conversations: number,
      avg_parties_per_conversation: number,
      avg_dialogs_per_conversation: number,
      avg_analysis_per_conversation: number,
      avg_attachments_per_conversation: number,
      avg_duration_per_conversation: number,
      avg_size_per_conversation: number,
      max_parties_in_conversation: number,
      max_dialogs_in_conversation: number
    },
    temporal_content: Array<{
      month: string,
      vcon_count: number,
      dialog_count: number,
      analysis_count: number,
      attachment_count: number,
      total_duration: number
    }>
  }
}
```

***

### get\_database\_health\_metrics

Get database health metrics including performance indicators and optimization recommendations.

**Input Parameters:**

```typescript
{
  include_performance_metrics?: boolean,  // Include performance metrics (default: true)
  include_storage_efficiency?: boolean,   // Include storage efficiency (default: true)
  include_index_health?: boolean,         // Include index health (default: true)
  include_connection_metrics?: boolean,   // Include connection metrics (default: true)
  include_recommendations?: boolean       // Include recommendations (default: true)
}
```

**Response:**

```typescript
{
  success: true,
  database_health_metrics: {
    timestamp: string,
    overall_score: number,
    metrics: {
      performance: Array<{
        table_name: string,
        sequential_scans: number,
        index_scans: number,
        inserts: number,
        updates: number,
        deletes: number,
        live_rows: number,
        dead_rows: number,
        dead_row_percentage: number,
        index_usage_ratio: number
      }>,
      storage: Array<{
        table_name: string,
        total_size: string,
        table_size: string,
        index_size: string,
        index_size_percentage: number
      }>,
      indexes: Array<{
        table_name: string,
        index_name: string,
        scans: number,
        rows_read: number,
        rows_fetched: number,
        index_size: string,
        health_status: 'UNUSED' | 'LOW_USAGE' | 'ACTIVE'
      }>,
      connections: {
        heap_read: number,
        heap_hit: number,
        cache_hit_ratio: number,
        idx_read: number,
        idx_hit: number,
        idx_cache_hit_ratio: number
      }
    },
    recommendations: string[],
    alerts: string[]
  }
}
```

***

## Database Size Tools

### get\_database\_size\_info

Get database size information and smart recommendations for query limits. Essential for large databases to prevent memory exhaustion.

**Input Parameters:**

```typescript
{
  include_recommendations?: boolean  // Include smart recommendations (default: true)
}
```

**Response:**

```typescript
{
  success: true,
  database_size_info: {
    total_vcons: number,
    total_size_bytes: number,
    total_size_pretty: string,
    size_category: 'small' | 'medium' | 'large' | 'very_large',
    recommendations: {
      max_basic_search_limit: number,
      max_content_search_limit: number,
      max_semantic_search_limit: number,
      max_analytics_limit: number,
      recommended_response_format: string,
      memory_warning: boolean
    },
    table_sizes: {
      [table_name]: {
        row_count: number,
        size_bytes: number,
        size_pretty: string
      }
    }
  }
}
```

**Example:**

```typescript
{
  "include_recommendations": true
}
```

***

### get\_smart\_search\_limits

Get smart search limits based on database size and query complexity. Helps prevent memory exhaustion by suggesting appropriate limits.

**Input Parameters:**

```typescript
{
  query_type: 'basic' | 'content' | 'semantic' | 'hybrid' | 'analytics',
  estimated_result_size?: 'small' | 'medium' | 'large' | 'unknown'  // Default: 'unknown'
}
```

**Response:**

```typescript
{
  success: true,
  smart_limits: {
    query_type: string,
    estimated_result_size: string,
    recommended_limit: number,
    recommended_response_format: string,
    memory_warning: boolean,
    explanation: string
  }
}
```

**Example:**

```typescript
{
  "query_type": "content",
  "estimated_result_size": "large"
}
```

***

## Schema & Examples

### get\_schema

Get vCon schema definition.

**Input Parameters:**

```typescript
{
  format?: "json_schema" | "typescript" | "openapi",  // Default: "json_schema"
  version?: string        // vCon version, default: "latest"
}
```

**Response:**

```typescript
{
  success: boolean,
  format: string,
  version: string,
  schema: object | string
}
```

***

### get\_examples

Get example vCons.

**Input Parameters:**

```typescript
{
  example_type: "minimal" | "phone_call" | "chat" | "email" | "video" | "full_featured",
  format?: "json" | "yaml"  // Default: "json"
}
```

**Response:**

```typescript
{
  success: boolean,
  example_type: string,
  format: string,
  vcon: object | string
}
```

**Example Types:**

* **minimal** - Bare minimum required fields
* **phone\_call** - Phone conversation example
* **chat** - Text chat example
* **email** - Email thread example
* **video** - Video meeting example
* **full\_featured** - All features demonstrated

***

## Error Responses

All tools return errors in this format:

```typescript
{
  success: false,
  error: string,
  details?: any
}
```

**Common Error Codes:**

* `VALIDATION_ERROR` - Invalid input parameters
* `NOT_FOUND` - vCon or resource not found
* `DATABASE_ERROR` - Database operation failed
* `PERMISSION_DENIED` - Insufficient permissions
* `RATE_LIMIT_EXCEEDED` - Too many requests

***

## Usage Notes

### Best Practices

1. **Always validate** - Use `validate_before_insert` for create operations
2. **Use appropriate search** - Choose the right search tool for your use case
3. **Tag consistently** - Establish a tagging schema
4. **Monitor performance** - Use database tools regularly
5. **Handle errors** - Check `success` field in all responses

### Rate Limits

* Search operations: 100 requests/minute
* Create operations: 50 requests/minute
* Other operations: 200 requests/minute

### Pagination

For search results:

* Use `limit` and `offset` parameters
* Check `has_more` in response
* Maximum `limit` is 1000

***

## Next Steps

* See [Resources](/api-reference/resources) for URI-based access
* See [Prompts](/api-reference/prompts) for query templates
* See [TypeScript Types](/api-reference/types) for type definitions
* See [Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/examples/README.md) for practical usage


# MCP Resources

Resources provide URI-based access to vCon data through the Model Context Protocol. They offer a simpler alternative to tools for common data access patterns.

## Overview

Resources use versioned URI schemes to access vCon data:

* **Browsing** - List recent conversations
* **Lookup** - Fetch specific vCons by UUID
* **Discovery** - Get lightweight ID lists and live attachment or analysis categories
* **Subresources** - Access specific vCon components (parties, dialog, analysis, attachments)
* **Derived** - Get filtered data (transcripts, summaries, tags, and generic category-backed reads)

For complex searches and modifications, use [MCP Tools](/api-reference/tools) instead.

***

## Resource Namespace

All resources use versioned namespaces:

```
vcon://v1/discovery/...
vcon://v1/vcons/...
```

This allows for future schema evolution without breaking existing clients.

When a classification lives in attachments or analysis, prefer this flow:

1. Discover available `type` or `purpose` values.
2. Read the matching filtered resource for a specific vCon.
3. Fall back to tags only when the classification really lives in the tags attachment.

***

## Collection Resources

### vcon://v1/vcons/recent

Get the most recently created vCons with full data.

**URI Patterns:**

* `vcon://v1/vcons/recent` - Get 10 most recent vCons (default)
* `vcon://v1/vcons/recent/25` - Get custom number (max 100)

**Response:**

```json
{
  "count": 10,
  "limit": 10,
  "vcons": [
    {
      "vcon": "0.4.0",
      "uuid": "123e4567-e89b-12d3-a456-426614174000",
      "created_at": "2025-10-14T10:30:00Z",
      "subject": "Customer Support Call",
      "parties": [...],
      "dialog": [...],
      "analysis": [...],
      "attachments": [...]
    }
  ]
}
```

**Use Cases:**

* Dashboard views
* Recent activity monitoring
* Quick access to latest conversations

***

### vcon://v1/vcons/recent/ids

Get lightweight list of recent vCon IDs for efficient browsing.

**URI Patterns:**

* `vcon://v1/vcons/recent/ids` - Get 10 most recent IDs (default)
* `vcon://v1/vcons/recent/ids/25` - Get custom number (max 100)

**Response:**

```json
{
  "count": 10,
  "limit": 10,
  "vcons": [
    {
      "uuid": "123e4567-e89b-12d3-a456-426614174000",
      "created_at": "2025-10-14T10:30:00Z",
      "subject": "Customer Support Call"
    }
  ]
}
```

**Use Cases:**

* Navigation menus
* Autocomplete suggestions
* Performance-sensitive displays

***

### vcon://v1/vcons/ids

Browse all vCon IDs with cursor-based pagination.

**URI Patterns:**

* `vcon://v1/vcons/ids` - Get first 100 IDs (default)
* `vcon://v1/vcons/ids/500` - Get custom number (max 1000)
* `vcon://v1/vcons/ids/100/after/{timestamp}` - Get next page

**Response:**

```json
{
  "count": 100,
  "limit": 100,
  "has_more": true,
  "next_cursor": "2025-10-14T09:30:00Z",
  "vcons": [
    {
      "uuid": "123e4567-e89b-12d3-a456-426614174000",
      "created_at": "2025-10-14T10:30:00Z",
      "subject": "Customer Support Call"
    }
  ]
}
```

**Pagination Example:**

```typescript
// First page
const page1 = await readResource("vcon://v1/vcons/ids/100");

// Next page
if (page1.has_more) {
  const page2 = await readResource(
    `vcon://v1/vcons/ids/100/after/${encodeURIComponent(page1.next_cursor)}`
  );
}
```

**Use Cases:**

* Full database exports
* Bulk operations
* Data migration

***

## Entity Resources

### vcon://v1/vcons/{uuid}

Retrieve a complete vCon object by UUID.

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000`

**Response:**

```json
{
  "vcon": "0.4.0",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "created_at": "2025-10-14T10:30:00Z",
  "updated_at": "2025-10-14T11:00:00Z",
  "subject": "Customer Support Call",
  "parties": [
    {
      "name": "Agent Smith",
      "mailto": "smith@company.com"
    },
    {
      "name": "John Doe",
      "tel": "+1-555-1234"
    }
  ],
  "dialog": [
    {
      "type": "text",
      "start": "2025-10-14T10:30:00Z",
      "parties": [0, 1],
      "body": "Hello, how can I help you?"
    }
  ],
  "analysis": [
    {
      "type": "sentiment",
      "vendor": "OpenAI",
      "body": "{\"sentiment\": \"positive\"}"
    }
  ],
  "attachments": [
    {
      "type": "tags",
      "encoding": "json",
      "body": "[\"department:support\", \"priority:high\"]"
    }
  ]
}
```

**Use Cases:**

* Display full conversation details
* Export single conversation
* Reference lookup

***

### vcon://v1/vcons/{uuid}/metadata

Get only metadata fields, excluding conversation content arrays.

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/metadata`

**Response:**

```json
{
  "vcon": "0.4.0",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "created_at": "2025-10-14T10:30:00Z",
  "updated_at": "2025-10-14T11:00:00Z",
  "subject": "Customer Support Call",
  "extensions": [],
  "critical": []
}
```

**Excluded Fields:**

* `parties`
* `dialog`
* `analysis`
* `attachments`

**Use Cases:**

* Quick metadata checks
* Performance-sensitive queries
* Metadata-only displays

***

## Subresources

These resources provide direct access to specific components of a vCon.

### vcon://v1/vcons/{uuid}/parties

Get only the parties array from a vCon.

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/parties`

**Response:**

```json
{
  "parties": [
    {
      "name": "Agent Smith",
      "mailto": "smith@company.com"
    },
    {
      "name": "John Doe",
      "tel": "+1-555-1234"
    }
  ]
}
```

**Use Cases:**

* Display participant lists
* Contact information extraction
* Party-specific queries

***

### vcon://v1/vcons/{uuid}/dialog

Get only the dialog array from a vCon.

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/dialog`

**Response:**

```json
{
  "dialog": [
    {
      "type": "text",
      "start": "2025-10-14T10:30:00Z",
      "parties": [0, 1],
      "body": "Hello, how can I help you?"
    },
    {
      "type": "text",
      "start": "2025-10-14T10:31:00Z",
      "parties": [1],
      "body": "I need help with my account."
    }
  ]
}
```

**Use Cases:**

* Display conversation history
* Timeline views
* Dialog-specific processing

***

### vcon://v1/vcons/{uuid}/analysis

Get only the analysis array from a vCon.

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/analysis`

**Response:**

```json
{
  "analysis": [
    {
      "type": "sentiment",
      "vendor": "OpenAI",
      "product": "GPT-4",
      "body": "{\"sentiment\": \"positive\", \"score\": 0.85}",
      "encoding": "json"
    },
    {
      "type": "summary",
      "vendor": "Anthropic",
      "product": "Claude-3.5",
      "body": "Customer inquired about account access.",
      "encoding": "none"
    }
  ]
}
```

**Use Cases:**

* Display AI analysis results
* Analytics dashboards
* Insights extraction

***

### vcon://v1/vcons/{uuid}/attachments

Get only the attachments array from a vCon.

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/attachments`

**Response:**

```json
{
  "attachments": [
    {
      "type": "tags",
      "encoding": "json",
      "body": "[\"department:support\", \"priority:high\"]"
    },
    {
      "type": "document",
      "filename": "invoice.pdf",
      "mediatype": "application/pdf",
      "url": "https://storage.example.com/invoice.pdf"
    }
  ]
}
```

**Use Cases:**

* Display attached files
* Download documents
* Metadata extraction

***

## Discovery Resources

Use these resources to discover live attachment and analysis categories before reading a specific vCon by the matching field. For attachments, `purpose` is canonical and `type` is compatibility-only.

### vcon://v1/discovery/attachments/types

List discovered legacy attachment `type` values with counts.

Use this only when you are working with older datasets that still classify attachments through `type`. For spec-facing clients, prefer `vcon://v1/discovery/attachments/purposes`.

**Response:**

```json
{
  "count": 2,
  "attachment_types": [
    { "value": "document", "count": 14 },
    { "value": "tags", "count": 8 }
  ]
}
```

### vcon://v1/discovery/attachments/purposes

List discovered attachment `purpose` values with counts.

This is the canonical spec-facing attachment discovery surface.

**Response:**

```json
{
  "count": 2,
  "attachment_purposes": [
    { "value": "dealer_info", "count": 5 },
    { "value": "classification", "count": 3 }
  ]
}
```

### vcon://v1/discovery/analysis/types

List discovered analysis `type` values with counts.

**Response:**

```json
{
  "count": 2,
  "analysis_types": [
    { "value": "summary", "count": 11 },
    { "value": "transcript", "count": 9 }
  ]
}
```

***

## Generic Filtered Resources

These resources expose attachment and analysis categories as first-class read surfaces instead of requiring special-case resource definitions.

### vcon://v1/vcons/{uuid}/attachments/type/{type}

Read attachments filtered by legacy attachment `type`.

Use this only for compatibility with older data. New clients should prefer the purpose-based resource below.

### vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}

Read attachments filtered by attachment `purpose`.

This is the canonical spec-facing attachment read path.

### vcon://v1/vcons/{uuid}/analysis/type/{type}

Read analysis filtered by analysis `type`.

**Example response:**

```json
{
  "count": 1,
  "purpose": "dealer_info",
  "attachments": [
    {
      "type": "document",
      "purpose": "dealer_info",
      "filename": "dealer.json"
    }
  ]
}
```

***

## Derived Resources

These resources filter and transform vCon data for specific use cases. Internally they follow the same shared filtering path as the generic category-backed resources.

### vcon://v1/vcons/{uuid}/transcript

Get transcript analysis from a vCon (filters analysis where type='transcript').

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/transcript`

**Response:**

```json
{
  "count": 1,
  "transcripts": [
    {
      "type": "transcript",
      "vendor": "Google Cloud",
      "product": "Speech-to-Text",
      "dialog": [0],
      "body": "{\"transcript\": \"Hello, how can I help you?\", \"confidence\": 0.98}",
      "encoding": "json"
    }
  ]
}
```

**Use Cases:**

* Display transcriptions
* Text analysis
* Speech-to-text results

***

### vcon://v1/vcons/{uuid}/summary

Get summary analysis from a vCon (filters analysis where type='summary').

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/summary`

**Response:**

```json
{
  "count": 1,
  "summaries": [
    {
      "type": "summary",
      "vendor": "Anthropic",
      "product": "Claude-3.5",
      "body": "Customer called about billing issue. Agent provided refund and apology.",
      "encoding": "none"
    }
  ]
}
```

**Use Cases:**

* Display conversation summaries
* Quick overview
* Report generation

***

### vcon://v1/vcons/{uuid}/tags

Get tags from a vCon (filters attachments where type='tags' and parses as object).

**URI Pattern:**

* `vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/tags`

**Response:**

```json
{
  "tags": {
    "department": "support",
    "priority": "high",
    "status": "resolved",
    "customer_id": "12345"
  }
}
```

**Note:** If no tags exist, returns `{"tags": {}}`

**Use Cases:**

* Display metadata tags
* Filter by categories
* Custom organization

***

## Resources vs. Tools

### Use Resources When:

✅ **Browsing** - Viewing recent or all vCons\
✅ **Lookup** - Fetching specific vCon by UUID\
✅ **Simple** - Browsing, lookup, and category-backed reads after discovery\
✅ **Read-only** - Just retrieving data\
✅ **Subcomponents** - Accessing specific vCon arrays

### Use Tools When:

🔧 **Searching** - Filtering by tags, dates, content\
🔧 **Modifying** - Creating, updating, deleting\
🔧 **Complex** - Multi-criteria queries\
🔧 **Operations** - Adding dialog, analysis, attachments

***

## Usage Examples

### Claude Desktop

Resources are automatically available in Claude Desktop when the MCP server is configured:

```typescript
// Browse recent conversations
const recent = await readResource("vcon://v1/vcons/recent/20");

// Get specific conversation
const vcon = await readResource("vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000");

// Get just parties
const parties = await readResource("vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/parties");

// Discover live attachment purposes
const purposes = await readResource("vcon://v1/discovery/attachments/purposes");

// Read only dealer info attachments
const dealerInfo = await readResource(
  "vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/attachments/purpose/dealer_info"
);

// Get summary
const summary = await readResource("vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/summary");

// Get tags
const tags = await readResource("vcon://v1/vcons/123e4567-e89b-12d3-a456-426614174000/tags");
```

### Custom MCP Client

```typescript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

const client = new Client({
  name: 'my-client',
  version: '1.0.0'
});

// List available resources
const resources = await client.listResources();

// Read a resource
const result = await client.readResource({
  uri: 'vcon://v1/vcons/recent/10'
});

console.log(result.contents[0].text);
```

### cURL (via MCP HTTP Bridge)

```bash
# Get recent vCons
curl http://localhost:3000/resources/vcon%3A%2F%2Fv1%2Fvcons%2Frecent%2F10

# Get specific vCon
curl http://localhost:3000/resources/vcon%3A%2F%2Fv1%2Fvcons%2F123e4567-e89b-12d3-a456-426614174000

# Get transcript
curl http://localhost:3000/resources/vcon%3A%2F%2Fv1%2Fvcons%2F123e4567-e89b-12d3-a456-426614174000%2Ftranscript
```

***

## Performance Characteristics

### Resource Efficiency

| Resource                            | Typical Response Time | Network Size | Database Queries |
| ----------------------------------- | --------------------- | ------------ | ---------------- |
| `vcon://v1/vcons/recent/ids`        | \~50ms                | \~5KB        | 1                |
| `vcon://v1/vcons/recent`            | \~200ms               | \~50KB       | 1-3              |
| `vcon://v1/vcons/{uuid}`            | \~100ms               | \~20KB       | 1-2              |
| `vcon://v1/vcons/{uuid}/metadata`   | \~50ms                | \~2KB        | 1                |
| `vcon://v1/vcons/{uuid}/parties`    | \~75ms                | \~3KB        | 1                |
| `vcon://v1/vcons/{uuid}/transcript` | \~100ms               | \~10KB       | 1                |
| `vcon://v1/vcons/ids/1000`          | \~500ms               | \~100KB      | 1                |

### Optimization Tips

1. **Use IDs resources** for navigation and lists
2. **Use metadata** when you don't need conversation content
3. **Use subresources** to fetch only what you need
4. **Use derived resources** for filtered data
5. **Paginate** large lists with cursor-based pagination
6. **Cache** frequently accessed vCons client-side
7. **Batch** requests when possible

***

## Error Handling

Resources return errors in standard MCP format:

```json
{
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "message": "vCon with UUID 123... not found"
  }
}
```

**Common Error Codes:**

* `RESOURCE_NOT_FOUND` - Invalid URI or UUID doesn't exist
* `INVALID_URI` - Malformed URI pattern
* `DATABASE_ERROR` - Database connection or query failed
* `PERMISSION_DENIED` - Insufficient permissions

**Error Handling Example:**

```typescript
try {
  const vcon = await readResource("vcon://v1/vcons/invalid-uuid");
} catch (error) {
  if (error.code === 'RESOURCE_NOT_FOUND') {
    console.log('vCon not found');
  } else {
    console.error('Unexpected error:', error);
  }
}
```

***

## Limitations

### Not Supported via Resources:

❌ **Filtering** - Use `search_vcons` or `search_by_tags` tools\
❌ **Sorting** - Use tools with custom ordering\
❌ **Tag filtering** - Use `search_by_tags` tool\
❌ **Content search** - Use `search_vcons_content` tool\
❌ **Semantic search** - Use `search_vcons_semantic` tool\
❌ **Modifications** - Use CRUD tools\
❌ **Complex queries** - Use appropriate search tools

***

## Migration Guide

### Breaking Changes in v1

All resource URIs have changed from `vcon://` to `vcon://v1/vcons/`:

**Old Namespace:**

```
vcon://recent
vcon://recent/ids
vcon://list/ids
vcon://uuid/{uuid}
vcon://uuid/{uuid}/metadata
```

**New Namespace:**

```
vcon://v1/vcons/recent
vcon://v1/vcons/recent/ids
vcon://v1/vcons/ids
vcon://v1/vcons/{uuid}
vcon://v1/vcons/{uuid}/metadata
```

### Migration Steps

1. **Update all resource URIs** in your code to use `vcon://v1/vcons/` prefix
2. **Replace `vcon://list/ids`** with `vcon://v1/vcons/ids`
3. **Replace `vcon://uuid/`** with `vcon://v1/vcons/`
4. **Use new subresources** instead of accessing nested fields
5. **Use derived resources** for common filtered queries

### Example Migration

```typescript
// OLD
const recent = await readResource("vcon://recent/10");
const vcon = await readResource("vcon://uuid/123.../");
const ids = await readResource("vcon://list/ids");

// NEW
const recent = await readResource("vcon://v1/vcons/recent/10");
const vcon = await readResource("vcon://v1/vcons/123.../");
const ids = await readResource("vcon://v1/vcons/ids");

// NEW CAPABILITIES
const parties = await readResource("vcon://v1/vcons/123.../parties");
const transcript = await readResource("vcon://v1/vcons/123.../transcript");
const tags = await readResource("vcon://v1/vcons/123.../tags");
```

***

## Next Steps

* See [Tools Reference](/api-reference/tools) for complex operations
* See [Prompts Reference](/api-reference/prompts) for query templates
* See [Examples](https://github.com/vcon-dev/vcon-mcp/blob/main/examples/resources.md) for practical usage
* See [Getting Started](https://github.com/vcon-dev/vcon-mcp/blob/main/guide/getting-started.md) for setup


# MCP Prompts

Prompts are reusable query templates that help users effectively search and retrieve vCons. They provide guided workflows for common search patterns.

## Overview

The vCon MCP Server provides 9 prompt templates:

1. [**find\_by\_exact\_tags**](#find_by_exact_tags) - Exact tag matching
2. [**find\_by\_semantic\_search**](#find_by_semantic_search) - AI-powered meaning search
3. [**find\_by\_keywords**](#find_by_keywords) - Keyword/phrase search
4. [**find\_recent\_by\_topic**](#find_recent_by_topic) - Recent conversations by topic
5. [**find\_by\_party**](#find_by_party) - Search by party
6. [**discover\_available\_tags**](#discover_available_tags) - Explore available tags
7. [**complex\_search**](#complex_search) - Multi-criteria searches
8. [**find\_similar\_conversations**](#find_similar_conversations) - Find similar vCons
9. [**help\_me\_search**](#help_me_search) - Query strategy guidance

***

## Prompt Definitions

### find\_by\_exact\_tags

Find vCons using exact tag matches for precise queries.

**Arguments:**

* `tag_criteria` (required): Natural language description of tags to match
  * Examples: "angry customers", "high priority sales", "department support"
* `date_range` (optional): Date range description
  * Examples: "from June", "last week", "Q1 2024"

**Best For:**

* Queries with known categories
* Filtering by metadata
* Precise department/priority/status matching

**Example Usage:**

```
Query: "Find all angry customers from June"
tag_criteria: "angry customers"
date_range: "from June"

→ Guides to: search_by_tags with {sentiment: "angry"}
```

**Strategy:**

1. Parse tag criteria to identify key-value pairs
2. Convert date range to ISO 8601
3. Use `search_by_tags` tool
4. Handle exact matching (no fuzzy logic)

***

### find\_by\_semantic\_search

Find vCons using AI-powered semantic search to understand meaning and intent.

**Arguments:**

* `search_description` (required): Natural language description
  * Examples: "angry customers", "billing disputes", "positive feedback"
* `date_range` (optional): Date range description

**Best For:**

* Concept-based queries
* Finding similar meanings
* Natural language questions
* Fuzzy matching needs

**Example Usage:**

```
Query: "Find frustrated customers from last month"
search_description: "frustrated customers"
date_range: "last month"

→ Guides to: search_vcons_semantic
→ Matches: angry, upset, dissatisfied, complaining (similar concepts)
```

**Strategy:**

1. Understand intent (AI embeddings)
2. Find related concepts and synonyms
3. Use `search_vcons_semantic` tool
4. Adjust similarity threshold as needed

***

### find\_by\_keywords

Find vCons containing specific keywords or phrases.

**Arguments:**

* `keywords` (required): Keywords or phrases to search for
  * Examples: "refund", "billing issue", "technical support"
* `filters` (optional): Additional filters (tags, dates, parties)

**Best For:**

* Exact word matching
* Specific terminology
* Phrase searches
* ID or code lookups

**Example Usage:**

```
Query: "Find conversations mentioning 'refund' or 'billing issue'"
keywords: "refund OR billing issue"
filters: "department: support"

→ Guides to: search_vcons_content
```

**What Gets Searched:**

* ✅ Subject lines
* ✅ Dialog bodies
* ✅ Analysis bodies
* ✅ Party information
* ❌ Attachments (not indexed)

**Strategy:**

1. Extract specific keywords
2. Parse additional filters
3. Use `search_vcons_content` tool
4. Review relevance scores and snippets

***

### find\_recent\_by\_topic

Find recent vCons filtered by topic or category.

**Arguments:**

* `topic` (required): Topic or category
  * Examples: "support", "sales", "billing"
* `timeframe` (optional): Recency timeframe
  * Examples: "today", "this week", "last 7 days", "this month"
  * Default: "recent" (last 30 days)

**Best For:**

* Dashboard views
* Recent activity monitoring
* Time-sensitive queries
* Category browsing

**Example Usage:**

```
Query: "Show me recent support calls"
topic: "support"
timeframe: "this week"

→ Combines date filtering with topic search
```

**Strategy:**

1. Convert timeframe to date range
2. Determine if topic is tag or concept
3. Choose appropriate search tool
4. Apply date filtering

***

### find\_by\_party

Find all vCons involving a specific party or participant.

**Arguments:**

* `party_identifier` (required): Customer/party identifier
  * Email: `john@example.com`
  * Phone: `+1-555-1234`
  * Name: `John Smith`
* `date_range` (optional): Date range to filter

**Best For:**

* Customer history lookup
* Party-specific searches
* Contact tracing
* Relationship mapping

**Example Usage:**

```
Query: "Find all conversations with john@example.com"
party_identifier: "john@example.com"

→ Guides to: search_vcons with party_email filter
```

**Search Behavior:**

* `party_name`: Case-insensitive partial match
* `party_email`: Exact match
* `party_tel`: Exact match

**Strategy:**

1. Identify party type (email/phone/name)
2. Use `search_vcons` with appropriate filter
3. Show all parties in each conversation
4. Suggest follow-up actions

***

### discover\_available\_tags

Discover what tags are available in the system for filtering.

**Arguments:**

* `tag_category` (optional): Focus on specific tag category
  * Examples: "department", "priority", "sentiment"

**Best For:**

* Exploring data
* Understanding tag schema
* Planning searches
* Documentation

**Example Usage:**

```
Query: "What tags are available for filtering?"
→ Uses: get_unique_tags with include_counts

Response shows:
{
  "department": ["sales", "support", "billing"],
  "priority": ["high", "medium", "low"],
  "sentiment": ["positive", "neutral", "negative"]
}
```

**Strategy:**

1. Use `get_unique_tags` tool
2. Organize by category
3. Show usage counts
4. Suggest example searches

***

### complex\_search

Perform complex searches combining multiple criteria: tags, keywords, dates, and semantic meaning.

**Arguments:**

* `search_criteria` (required): Complete search description
  * Example: "high-priority sales calls from Q1 mentioning pricing"

**Best For:**

* Multi-dimensional queries
* Business intelligence
* Complex filtering
* Advanced searches

**Example Usage:**

```
Query: "Find high-priority sales calls from Q1 where customer mentioned pricing"
search_criteria: "high-priority sales calls from Q1 mentioning pricing"

→ Parses into:
  - Tags: {priority: "high", department: "sales"}
  - Date: Q1 2024 (Jan 1 - Mar 31)
  - Content: "pricing"
→ Uses: search_vcons_hybrid or search_vcons_content
```

**Strategy:**

1. Parse criteria into components (tags, dates, keywords, concepts)
2. Choose best search strategy
3. Build comprehensive query
4. Refine results as needed

***

### find\_similar\_conversations

Find conversations similar to a specific vCon or topic.

**Arguments:**

* `reference` (required): vCon UUID or topic description
* `limit` (optional): Number of results (default: 10)

**Best For:**

* Similar issue lookup
* Pattern discovery
* Related conversation finding
* Contextual search

**Example Usage:**

```
Query: "Find conversations similar to this one"
reference: "123e4567-e89b-12d3-a456-426614174000"
limit: "10"

→ Uses semantic similarity to find related vCons
```

**Strategy:**

1. Determine if reference is UUID or description
2. Extract or generate embedding
3. Use `search_vcons_semantic` with similarity threshold
4. Adjust threshold for precision vs recall

***

### help\_me\_search

Get guidance on the best way to search for vCons based on your needs.

**Arguments:**

* `what_you_want` (required): Description of what you're trying to find

**Best For:**

* New users
* Complex queries
* Strategy planning
* Tool selection

**Example Usage:**

```
Query: "I want to find frustrated customers who complained about billing"
what_you_want: "frustrated customers who complained about billing"

→ Analyzes query type
→ Recommends: search_vcons_semantic or search_vcons_hybrid
→ Provides step-by-step guidance
```

**Decision Tree:**

| Query Type        | Recommended Tool               |
| ----------------- | ------------------------------ |
| Exact tag values  | `search_by_tags`               |
| Specific keywords | `search_vcons_content`         |
| Natural language  | `search_vcons_semantic`        |
| Mixed criteria    | `search_vcons_hybrid`          |
| Party information | `search_vcons` (party filters) |
| Date ranges       | Any tool + date filters        |

***

## Using Prompts

Prompts are filtered by the same `MCP_TOOLS_PROFILE` categories as tools. Every prompt is in the `read` category except `daily_activity_report` (`analytics`), so `readonly` and `public` deployments do not list it. See [Tools](/api-reference/tools#tool-categories) for the profiles.

### Claude Desktop

Prompts appear in the prompt selector:

```typescript
// User selects prompt: "find_by_exact_tags"
// Fills in arguments:
//   tag_criteria: "angry customers"
//   date_range: "June 2024"

// Claude receives guidance and executes appropriate tools
```

### Custom MCP Client

```typescript
import { Client } from '@modelcontextprotocol/sdk/client/index.js';

const client = new Client({
  name: 'my-client',
  version: '1.0.0'
});

// List available prompts
const prompts = await client.listPrompts();

// Get a specific prompt
const prompt = await client.getPrompt({
  name: 'find_by_exact_tags',
  arguments: {
    tag_criteria: 'angry customers',
    date_range: 'June 2024'
  }
});

// The prompt.messages array contains guidance
```

***

## Prompt Strategy Guide

### When to Use Each Prompt

```
📋 Known categories/tags → find_by_exact_tags
🔍 Specific words → find_by_keywords
🤖 Concepts/meaning → find_by_semantic_search
📅 Recent + topic → find_recent_by_topic
👤 Specific person → find_by_party
🏷️  Explore tags → discover_available_tags
🔧 Multiple criteria → complex_search
🔗 Similar content → find_similar_conversations
❓ Not sure → help_me_search
```

### Query Analysis Flow

```
1. Is it a simple query?
   → Yes: Use specific prompt (tags, keywords, party)
   → No: Continue

2. Does it involve multiple criteria?
   → Yes: Use complex_search
   → No: Continue

3. Is it concept-based or exact words?
   → Concept: Use find_by_semantic_search
   → Exact: Use find_by_keywords

4. Still unsure?
   → Use help_me_search
```

***

## Examples by Use Case

### Customer Service

```typescript
// Find recent angry customers
Prompt: find_recent_by_topic
  topic: "angry customers"
  timeframe: "this week"

// Find all conversations with customer
Prompt: find_by_party
  party_identifier: "customer@example.com"

// Find billing complaints
Prompt: find_by_keywords
  keywords: "billing complaint refund"
  filters: "department: support"
```

### Sales

```typescript
// Find high-value sales calls
Prompt: find_by_exact_tags
  tag_criteria: "high value sales"
  date_range: "this quarter"

// Find pricing discussions
Prompt: find_by_keywords
  keywords: "pricing discount contract"
  filters: "department: sales"

// Find successful sales patterns
Prompt: find_similar_conversations
  reference: "uuid-of-successful-call"
  limit: "20"
```

### Analytics

```typescript
// Explore available tags
Prompt: discover_available_tags

// Complex multi-criteria search
Prompt: complex_search
  search_criteria: "high-priority support calls from Q1 with negative sentiment"

// Find similar issues
Prompt: find_similar_conversations
  reference: "customer complaint about delays"
  limit: "50"
```

***

## Best Practices

### 1. Start Simple

Begin with specific prompts before moving to complex searches.

### 2. Discover First

Use `discover_available_tags` to understand your data before searching.

### 3. Refine Iteratively

Start broad, then narrow based on results.

### 4. Combine Filters

Use date ranges with every search for better performance.

### 5. Use Right Tool

Let prompts guide you to the appropriate search tool.

***

## Next Steps

* See [Tools Reference](/api-reference/tools) for tool details
* See [Resources Reference](/api-reference/resources) for URI-based access
* See [Search Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/guide/search.md) for search strategies
* See [Tag Guide](https://github.com/vcon-dev/vcon-mcp/tree/main/guide/tags.md) for tag management


# TypeScript Types

Complete TypeScript type definitions for the vCon MCP Server.

## Overview

The vCon MCP Server provides full type safety through TypeScript and Zod validation. All types comply with [IETF vCon Core](https://datatracker.ietf.org/doc/html/draft-ietf-vcon-vcon-core-02) specification.

***

## Core vCon Types

### VCon

Main vCon object representing a complete virtual conversation.

```typescript
interface VCon {
  // Core Metadata (Section 4.1)
  vcon: string;                    // vCon version (e.g., "0.4.0")
  uuid: string;                    // vCon UUID (RFC 4122)
  created_at: string;              // ISO 8601 timestamp
  updated_at?: string;             // ISO 8601 timestamp
  subject?: string;                // Conversation subject/title
  
  // Extensions (Section 4.1.3)
  extensions?: string[];           // Extension identifiers
  must_support?: string[];         // Required extension support
  
  // Components
  parties: Party[];                // Participants (at least 1 required)
  dialog?: Dialog[];               // Conversation segments
  analysis?: Analysis[];           // AI/ML analysis results
  attachments?: Attachment[];      // Additional files/data
  
  // Advanced Features
  group?: Group[];                 // vCon grouping (Section 4.6)
  redacted?: Record<string, any>;  // Redaction tracking
  appended?: Record<string, any>;  // Append-only modifications
}
```

***

### Party

Represents a participant in a conversation (Section 4.2).

```typescript
interface Party {
  // Contact Information
  tel?: string;                    // Phone number (E.164 format)
  sip?: string;                    // SIP URI
  mailto?: string;                 // Email address
  name?: string;                   // Display name
  
  // Identity & Verification (Section 4.2.3-4.2.6)
  stir?: string;                   // STIR/SHAKEN PASSporT
  did?: string;                    // Decentralized Identifier
  uuid?: string;                   // UUID for this party (RFC 4122)
  validation?: string;             // Identity validation info
  
  // Location (Section 4.2.7-4.2.9)
  timezone?: string;               // IANA timezone
  gmlpos?: string;                 // GML position
  civicaddress?: object;           // RFC 5139 civic address
  
  // vCard (Section 4.2.10)
  jcard?: object;                  // JSON vCard (RFC 7095)
  
  // At least one contact method required
}
```

**Party Examples:**

```typescript
// Phone party
{
  tel: "+1-555-1234",
  name: "John Doe",
  timezone: "America/New_York"
}

// Email party
{
  mailto: "support@example.com",
  name: "Support Agent",
  uuid: "550e8400-e29b-41d4-a716-446655440000"
}

// SIP party
{
  sip: "sip:user@example.com",
  name: "Alice Smith",
  stir: "eyJhbGciOiJFUzI1NiIsInR5cCI6InBhc3Nwb3J0..."
}
```

***

### Dialog

Represents a segment of conversation content (Section 4.3).

```typescript
interface Dialog {
  // Required
  type: "recording" | "text" | "transfer" | "incomplete";
  
  // Timing (Section 4.3.2-4.3.3)
  start?: string;                  // ISO 8601 timestamp
  duration?: number;               // Duration in seconds
  
  // Participants (Section 4.3.4-4.3.5)
  parties?: number | number[];     // Party index or array of indexes
  originator?: number;             // Party index of originator
  
  // Content
  body?: string;                   // Dialog content
  encoding?: "none" | "base64url" | "json";
  url?: string;                    // External URL
  
  // Media (Section 4.3.6-4.3.7)
  mediatype?: string;              // MIME type
  filename?: string;               // Original filename
  
  // Call Disposition (Section 4.3.9)
  disposition?: 
    | "no-answer"
    | "congestion"
    | "failed"
    | "busy"
    | "hung-up"
    | "voicemail-no-message";
  
  // Session Tracking (Section 4.3.10, 4.3.13, 4.3.14)
  session_id?: string;             // Session identifier
  application?: string;            // Application that created dialog
  message_id?: string;             // Message identifier
  
  // Integrity
  content_hash?: string | string[]; // SHA-256 hash
}
```

**Dialog Examples:**

```typescript
// Text message
{
  type: "text",
  start: "2025-10-14T10:30:00Z",
  parties: [0, 1],
  originator: 1,
  body: "Hello, I need help with my account.",
  encoding: "none"
}

// Audio recording
{
  type: "recording",
  start: "2025-10-14T10:30:00Z",
  duration: 185.5,
  parties: [0, 1],
  mediatype: "audio/mpeg",
  filename: "call-recording.mp3",
  url: "https://storage.example.com/recordings/abc123.mp3",
  encoding: "none"
}

// Video call
{
  type: "recording",
  start: "2025-10-14T14:00:00Z",
  duration: 3600,
  parties: [0, 1, 2],
  mediatype: "video/mp4",
  session_id: "video-call-abc123",
  application: "Zoom",
  disposition: "hung-up"
}
```

***

### Analysis

AI/ML analysis results for conversation content (Section 4.5).

```typescript
interface Analysis {
  // Required
  type: string;                    // Analysis type (see types below)
  vendor: string;                  // REQUIRED: Vendor/producer
  
  // References (Section 4.5.2)
  dialog?: number | number[];      // Dialog index(es) analyzed
  
  // Product Info (Section 4.5.6-4.5.7)
  product?: string;                // Product/model name
  schema?: string;                 // Schema identifier/version
  
  // Content (Section 4.5.8)
  body?: string;                   // Analysis content (any format)
  encoding?: "none" | "json" | "base64url";
  url?: string;                    // External URL
  
  // Media
  mediatype?: string;              // MIME type of body
  filename?: string;               // Filename if applicable
  
  // Integrity
  content_hash?: string | string[]; // SHA-256 hash
}
```

**Common Analysis Types:**

| Type            | Description              | Body Format                  |
| --------------- | ------------------------ | ---------------------------- |
| `summary`       | Conversation summary     | Text or JSON                 |
| `transcript`    | Speech-to-text           | Text or JSON with timestamps |
| `translation`   | Language translation     | Text or JSON                 |
| `sentiment`     | Sentiment analysis       | JSON with scores             |
| `keywords`      | Keyword extraction       | JSON array                   |
| `entities`      | Named entity recognition | JSON                         |
| `topics`        | Topic classification     | JSON                         |
| `action_items`  | Action item extraction   | JSON array                   |
| `pii_detection` | PII identification       | JSON                         |

**Analysis Examples:**

```typescript
// Sentiment analysis
{
  type: "sentiment",
  vendor: "OpenAI",
  product: "GPT-4",
  schema: "v1.0",
  dialog: [0],
  body: JSON.stringify({
    sentiment: "positive",
    score: 0.85,
    confidence: 0.92
  }),
  encoding: "json"
}

// Transcript
{
  type: "transcript",
  vendor: "Google Cloud",
  product: "Speech-to-Text",
  dialog: [0],
  body: JSON.stringify({
    transcript: "Hello, I need help with my account.",
    confidence: 0.98,
    language: "en-US"
  }),
  encoding: "json"
}

// Summary
{
  type: "summary",
  vendor: "Anthropic",
  product: "Claude-3.5",
  body: "Customer called about billing issue. Agent provided refund.",
  encoding: "none"
}
```

***

### Attachment

Additional files or data associated with a conversation (Section 4.4).

```typescript
interface Attachment {
  // Type & Timing
  type?: string;                   // Attachment type
  start?: string;                  // ISO 8601 timestamp
  
  // References (Section 4.4.3-4.4.4)
  party?: number;                  // Associated party index
  dialog?: number;                 // Associated dialog index
  
  // Content
  body?: string;                   // Attachment content
  encoding?: "none" | "json" | "base64url";
  url?: string;                    // External URL
  
  // Media
  mediatype?: string;              // MIME type
  filename?: string;               // Original filename
  
  // Integrity
  content_hash?: string | string[]; // SHA-256 hash
}
```

**Special Attachment Types:**

```typescript
// Tags attachment (for metadata)
{
  type: "tags",
  encoding: "json",
  body: JSON.stringify([
    "department:sales",
    "priority:high",
    "customer_id:12345"
  ])
}

// PDF document
{
  type: "invoice",
  party: 0,
  mediatype: "application/pdf",
  filename: "invoice-12345.pdf",
  body: "base64-encoded-content",
  encoding: "base64url"
}

// Screenshot
{
  type: "screenshot",
  dialog: 0,
  mediatype: "image/png",
  filename: "error-screenshot.png",
  url: "https://storage.example.com/screenshots/abc.png",
  encoding: "none"
}
```

***

### Group

Reference to other vCons for grouping (Section 4.6).

```typescript
interface Group {
  // Reference
  uuid?: string;                   // UUID of referenced vCon
  url?: string;                    // External URL to vCon
  
  // Inline Content
  body?: string;                   // Inline vCon content
  encoding: "json";                // Must be 'json' per spec
  
  // Integrity
  content_hash?: string | string[]; // SHA-256 hash
  
  // Exactly one of: uuid, url, or body+encoding required
}
```

***

## MCP Tool Input Types

### CreateVConInput

```typescript
interface CreateVConInput {
  vcon_data: {
    vcon?: string;                 // Default: "0.4.0"
    uuid?: string;                 // Auto-generated if not provided
    subject?: string;
    parties: Party[];              // At least 1 required
    dialog?: Dialog[];
    analysis?: Analysis[];
    attachments?: Attachment[];
    extensions?: string[];
    must_support?: string[];
  };
  metadata?: {
    basename?: string;
    filename?: string;
    tags?: Record<string, string>;
  };
  validate_before_insert?: boolean; // Default: true
}
```

### SearchVConsInput

```typescript
interface SearchVConsInput {
  // Metadata Filters
  subject?: string;                // Subject text search
  party_name?: string;             // Party name search
  party_email?: string;            // Party email search
  party_tel?: string;              // Party phone search
  
  // Date Filters
  start_date?: string;             // ISO 8601
  end_date?: string;               // ISO 8601
  
  // Pagination
  limit?: number;                  // Default: 50, Max: 1000
  offset?: number;                 // For pagination
}
```

### SearchVConsContentInput

```typescript
interface SearchVConsContentInput {
  query: string;                   // REQUIRED: Search query
  tags?: Record<string, string>;   // Tag filters
  start_date?: string;             // ISO 8601
  end_date?: string;               // ISO 8601
  limit?: number;                  // Default: 50
  include_snippets?: boolean;      // Default: true
}
```

### SearchVConsSemanticInput

```typescript
interface SearchVConsSemanticInput {
  query?: string;                  // Natural language query
  embedding?: number[];            // Or provide embedding (384 dims)
  threshold?: number;              // Similarity threshold (0-1), default: 0.7
  tags?: Record<string, string>;   // Tag filters
  limit?: number;                  // Default: 20
}
```

### SearchVConsHybridInput

```typescript
interface SearchVConsHybridInput {
  query: string;                   // REQUIRED: Search query
  semantic_weight?: number;        // 0-1, default: 0.6
  tags?: Record<string, string>;   // Tag filters
  start_date?: string;             // ISO 8601
  end_date?: string;               // ISO 8601
  limit?: number;                  // Default: 30
}
```

### TagInput

```typescript
interface ManageTagInput {
  vcon_uuid: string;               // UUID (RFC 4122)
  action: "set" | "remove";        // Action to perform
  key: string;                     // Tag key
  value?: string | number | boolean; // Tag value (required for "set")
}

interface GetTagsInput {
  vcon_uuid: string;               // UUID (RFC 4122)
  key?: string;                    // Specific tag key (optional)
  default_value?: any;             // Default if key not found
}

interface SearchByTagsInput {
  tags: Record<string, string>;    // REQUIRED: Tag key-value pairs
  limit?: number;                  // Default: 50, Max: 100
}

interface GetUniqueTagsInput {
  include_counts?: boolean;        // Include usage statistics
  key_filter?: string;             // Filter by key substring
  min_count?: number;              // Minimum occurrence count
}
```

***

## MCP Response Types

### StandardResponse

```typescript
interface StandardResponse {
  success: boolean;
  message?: string;
  error?: string;
  details?: any;
}
```

### CreateVConResponse

```typescript
interface CreateVConResponse extends StandardResponse {
  uuid: string;
  vcon?: VCon;
}
```

### GetVConResponse

```typescript
interface GetVConResponse extends StandardResponse {
  vcon: VCon;
}
```

### SearchResponse

```typescript
interface SearchResponse<T> extends StandardResponse {
  count: number;
  results: T[];
  has_more?: boolean;
}
```

### SearchContentResult

```typescript
interface SearchContentResult {
  vcon_id: string;
  content_type: "subject" | "dialog" | "analysis" | "party";
  content_index?: number;
  relevance_score: number;
  snippet?: string;
  vcon?: VCon;
}
```

### SearchSemanticResult

```typescript
interface SearchSemanticResult {
  vcon_id: string;
  similarity_score: number;
  matched_content: {
    subject?: string;
    dialog_excerpts?: Array<{
      dialog_index: number;
      text: string;
      relevance: number;
    }>;
  };
  vcon?: VCon;
}
```

### SearchHybridResult

```typescript
interface SearchHybridResult {
  vcon_id: string;
  combined_score: number;
  keyword_score: number;
  semantic_score: number;
  vcon?: VCon;
}
```

### TagsResponse

```typescript
interface GetTagsResponse extends StandardResponse {
  vcon_uuid: string;
  tags: Record<string, string | number | boolean>;
  count: number;
}

interface GetTagResponse extends StandardResponse {
  key: string;
  value: any;
  exists: boolean;
}

interface UniqueTagsResponse extends StandardResponse {
  unique_keys: string[];
  unique_key_count: number;
  tags_by_key: Record<string, string[]>;
  counts_per_value?: Record<string, Record<string, number>>;
  total_vcons_with_tags: number;
}
```

***

## Validation

All types are validated using Zod schemas. Example:

```typescript
import { z } from 'zod';

const PartySchema = z.object({
  tel: z.string().optional(),
  sip: z.string().optional(),
  mailto: z.string().email().optional(),
  name: z.string().optional(),
  did: z.string().optional(),
  uuid: z.string().uuid().optional(),
  validation: z.string().optional(),
  timezone: z.string().optional(),
  jcard: z.any().optional(),
  gmlpos: z.string().optional(),
  civicaddress: z.any().optional()
}).refine(
  data => data.tel || data.sip || data.mailto,
  { message: "At least one contact method required" }
);
```

***

## Type Guards

```typescript
// Check if vCon is valid
function isValidVCon(obj: any): obj is VCon {
  return (
    typeof obj.vcon === 'string' &&
    typeof obj.uuid === 'string' &&
    Array.isArray(obj.parties) &&
    obj.parties.length > 0
  );
}

// Check dialog type
function isTextDialog(dialog: Dialog): boolean {
  return dialog.type === 'text';
}

// Check if analysis has JSON body
function hasJsonAnalysis(analysis: Analysis): boolean {
  return analysis.encoding === 'json' && !!analysis.body;
}
```

***

## Constants

```typescript
// vCon Version
export const VCON_VERSION = '0.4.0';

// Dialog Types
export const DIALOG_TYPES = ['recording', 'text', 'transfer', 'incomplete'] as const;

// Encoding Types
export const ENCODING_TYPES = ['none', 'base64url', 'json'] as const;

// Disposition Values
export const DISPOSITIONS = [
  'no-answer',
  'congestion',
  'failed',
  'busy',
  'hung-up',
  'voicemail-no-message'
] as const;

// Common Analysis Types
export const ANALYSIS_TYPES = [
  'summary',
  'transcript',
  'translation',
  'sentiment',
  'keywords',
  'entities',
  'topics',
  'action_items',
  'pii_detection'
] as const;
```

***

## Next Steps

* See [Tools Reference](/api-reference/tools) for tool definitions
* See [Database Schema](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/api/schema.md) for database structure
* See [Examples](https://github.com/vcon-dev/vcon-mcp/blob/main/examples/README.md) for usage examples
* See [vCon Spec](https://datatracker.ietf.org/doc/html/draft-ietf-vcon-vcon-core-02) for full specification


# Overview

Everything you need to build, extend, and contribute to the vCon MCP Server.

## Overview

This comprehensive development guide covers all aspects of working with the vCon MCP Server codebase:

* **System Architecture** - Understanding the design and components
* **Building & Testing** - Getting the server running locally
* **Extending Functionality** - Creating plugins and custom tools
* **Contributing** - Guidelines for code, testing, and documentation
* **Best Practices** - Code style, patterns, and standards

***

## Quick Start

```bash
# Clone the repository
git clone https://github.com/vcon-dev/vcon-mcp.git
cd vcon-mcp

# Install dependencies
npm install

# Set up environment
cp .env.example .env
# Edit .env with your Supabase credentials

# Build the project
npm run build

# Run tests
npm test

# Start development server
npm run dev
```

***

## Documentation Sections

### 📐 [Architecture](/development/architecture)

**Deep dive into system design:**

* Component architecture and layers
* Data flow and request handling
* Plugin system architecture
* Database design and search strategies
* Performance considerations
* Security architecture

**Perfect for:** Understanding how everything fits together

***

### 🔨 [Building from Source](/development/building)

**Complete build guide from scratch:**

* Prerequisites and environment setup
* Database schema setup
* Project structure creation
* Core implementation
* MCP server configuration
* Testing and validation
* Deployment preparation

**Perfect for:** First-time setup and deployment

***

### 🧪 [Testing](/development/testing)

**Comprehensive testing guide:**

* Unit testing with Vitest
* Integration testing patterns
* IETF spec compliance tests
* MCP tool testing
* Test fixtures and utilities
* Coverage requirements
* CI/CD integration

**Perfect for:** Ensuring code quality and correctness

***

### 🔌 [Plugin Development](/development/plugins)

**Create plugins to extend the server:**

* Plugin interface and lifecycle hooks
* Operation hooks (create, read, update, delete, search)
* Registering custom tools and resources
* Plugin configuration
* Example plugins (logging, access control)
* Testing plugins
* Publishing plugins

**Perfect for:** Adding custom functionality without modifying core

***

### 🛠️ [Custom Tools](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/custom-tools.md)

**Develop custom MCP tools:**

* Tool structure and schemas
* Input validation with Zod
* Implementing tool handlers
* Database access patterns
* External API integration
* Testing custom tools
* Best practices and examples

**Perfect for:** Adding new capabilities to the MCP interface

***

### 🔧 [Extending the Server](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/extending.md)

**Complete extension guide for resources, prompts, tools, and plugins:**

* When to use each extension type
* Adding custom resources (discoverable data access)
* Creating custom prompts (guided query templates)
* Building custom tools (executable operations)
* Packaging as plugins (reusable modules)
* Complete real-world examples
* Best practices and patterns

**Perfect for:** Understanding all extension options and choosing the right approach

***

### 🤖 [Embeddings & Search](/development/embeddings)

**AI-powered semantic search:**

* pgvector extension setup
* Embedding generation (OpenAI, local models)
* Vector indexing (HNSW, IVFFlat)
* Search strategies (keyword, semantic, hybrid)
* Performance optimization
* Cost considerations
* Batch processing

**Perfect for:** Implementing AI-powered search features

***

### 🤝 [Contributing Guide](/development/contributing)

**How to contribute to the project:**

* Code of conduct
* Getting started with contributions
* Development workflow
* Pull request process
* Commit message conventions
* Code review expectations
* Recognition and community

**Perfect for:** New contributors and community guidelines

***

### 📝 [Code Style Guide](/development/code-style)

**Coding standards and best practices:**

* TypeScript style guidelines
* Naming conventions
* File organization patterns
* Comments and documentation
* Error handling patterns
* Testing style
* Git practices

**Perfect for:** Writing consistent, maintainable code

***

### 📚 [Documentation Standards](/development/documentation)

**Writing and maintaining docs:**

* Documentation types (API, guides, examples)
* Writing style and tone
* Markdown standards
* Code example guidelines
* API documentation templates
* User guide structure
* Build and deployment

**Perfect for:** Contributing to documentation

***

## Project Structure

```
vcon-mcp/
├── src/
│   ├── index.ts              # MCP server entry point
│   ├── types/                # TypeScript type definitions
│   │   ├── vcon.ts          # IETF vCon types
│   │   └── mcp.ts           # MCP protocol types
│   ├── db/                   # Database layer
│   │   ├── client.ts        # Supabase client
│   │   └── queries.ts       # Database queries
│   ├── tools/                # MCP tools
│   │   ├── vcon-crud.ts     # CRUD operations
│   │   ├── search-tools.ts  # Search operations
│   │   └── tag-tools.ts     # Tag management
│   ├── resources/            # MCP resources
│   │   └── index.ts         # Resource handlers
│   ├── prompts/              # MCP prompts
│   │   └── index.ts         # Prompt templates
│   ├── hooks/                # Plugin system
│   │   └── index.ts         # Plugin interface
│   └── utils/                # Utilities
│       ├── validation.ts    # vCon validation
│       └── logger.ts        # Logging utilities
├── tests/                    # Test suites
│   ├── crud.test.ts         # CRUD tests
│   ├── search.test.ts       # Search tests
│   └── fixtures/            # Test data
├── docs/                     # Documentation
│   ├── guide/               # User guides
│   ├── api/                 # API reference
│   ├── development/         # Developer guides
│   ├── examples/            # Code examples
│   └── reference/           # Technical specs
├── supabase/                 # Database
│   └── migrations/          # SQL migrations
├── scripts/                  # Helper scripts
│   └── test-mcp-tools.ts   # Tool testing script
└── .github/                  # GitHub config
    └── workflows/           # CI/CD pipelines
```

***

## Tech Stack

### Core Technologies

* **Language**: TypeScript 5.x
* **Runtime**: Node.js 18+
* **Database**: PostgreSQL 15+ (via Supabase)
* **Protocol**: MCP (Model Context Protocol)
* **Validation**: Zod
* **Testing**: Vitest
* **Build**: TypeScript Compiler
* **Documentation**: VitePress

### Key Libraries

* `@modelcontextprotocol/sdk` - MCP protocol implementation
* `@supabase/supabase-js` - Database client
* `zod` - Runtime type validation
* `vitest` - Testing framework
* `pgvector` - Vector similarity search

***

## Development Workflow

### 1. Set Up Environment

```bash
# Install dependencies
npm install

# Configure environment
cp .env.example .env
# Edit .env with your credentials

# Initialize database
# Run migrations in Supabase dashboard
```

### 2. Make Changes

```bash
# Create feature branch
git checkout -b feature/your-feature

# Make your changes
# Edit src/ files

# Build and test
npm run build
npm test
```

### 3. Test Locally

```bash
# Run dev server
npm run dev

# Test with MCP Inspector
npm run test:console

# Or test with Claude Desktop
# Update claude_desktop_config.json
```

### 4. Submit Changes

```bash
# Run linter
npm run lint

# Run tests
npm test

# Commit changes
git add .
git commit -m "feat(scope): description"

# Push and create PR
git push origin feature/your-feature
```

***

## Learning Path

### For New Contributors

1. **Start Here**:
   * Read [Architecture](/development/architecture) to understand the system
   * Follow [Building Guide](/development/building) to set up locally
   * Review [Code Style Guide](/development/code-style) for standards
2. **Make Your First Contribution**:
   * Check issues tagged with `good-first-issue`
   * Read [Contributing Guide](/development/contributing)
   * Start with documentation or tests
3. **Advance Your Skills**:
   * Review [Extending Guide](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/extending.md) to understand all options
   * Create a [Plugin](/development/plugins) to add functionality
   * Develop a [Custom Tool](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/custom-tools.md)
   * Implement [Advanced Search](/development/embeddings)

### For Advanced Developers

1. **Deep Dive**:
   * Study the [Architecture](/development/architecture) in detail
   * Review database schema and RPC functions
   * Understand plugin system internals
2. **Extend the System**:
   * Master the [Extension Guide](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/extending.md)
   * Build complex plugins with resources and tools
   * Add new search algorithms
   * Optimize performance
3. **Contribute Back**:
   * Improve core functionality
   * Enhance documentation
   * Mentor new contributors

***

## Testing Your Changes

### Unit Tests

```bash
# Run all tests
npm test

# Run specific test file
npm test -- search.test.ts

# Run with coverage
npm run test:coverage

# Watch mode
npm test -- --watch
```

### Integration Tests

```bash
# Test with MCP Inspector
npm run test:console

# Test with real client
# Configure Claude Desktop and test manually
```

### Compliance Tests

```bash
# Run IETF spec compliance tests
npm run test:compliance
```

***

## Getting Help

### Resources

* **Documentation**: Browse `/docs` for comprehensive guides
* **GitHub Issues**: Search for similar issues or questions
* **GitHub Discussions**: Ask questions and share ideas
* **Code Examples**: Check `/tests` and `/docs/examples`
* **IETF Spec**: Read the vCon specification for details

### Where to Ask

* **Questions**: GitHub Discussions
* **Bugs**: GitHub Issues with bug report template
* **Features**: GitHub Issues with feature request template
* **Security**: Email maintainers privately

***

## Contributing

We welcome contributions of all types:

* **Code**: New features, bug fixes, optimizations
* **Documentation**: Guides, examples, API docs
* **Testing**: Test cases, fixtures, tools
* **Design**: Architecture proposals, refactoring
* **Community**: Answering questions, reviewing PRs

See [Contributing Guide](/development/contributing) for detailed instructions.

***

## Community

* **GitHub**: <https://github.com/vcon-dev/vcon-mcp>
* **Issues**: Report bugs and request features
* **Discussions**: Ask questions and share ideas
* **IETF vCon WG**: <https://datatracker.ietf.org/wg/vcon/>

***

## License

The vCon MCP Server is released under the MIT License. See [LICENSE](https://github.com/vcon-dev/vcon-mcp/blob/main/LICENSE/README.md) for details.

By contributing, you agree that your contributions will be licensed under the MIT License.

***

**Ready to contribute?** Start with the [Contributing Guide](/development/contributing) and choose a task that interests you!

**Need help?** Don't hesitate to ask questions in GitHub Discussions. We're here to help! 🚀


# Architecture

Deep dive into the vCon MCP Server architecture, design patterns, and implementation details.

## Overview

The vCon MCP Server is built as a layered architecture connecting AI assistants to conversation data through the Model Context Protocol (MCP).

```
┌─────────────────────────────────────────────────────────────┐
│                      AI Assistants                          │
│              (Claude Desktop, Custom Clients)               │
└────────────────────┬────────────────────────────────────────┘
                     │ MCP Protocol (stdio/HTTP)
┌────────────────────▼──────────────────┬─────────────────────┐
│            MCP Server Layer          │   REST API (Koa)    │
│  ┌──────────┐ ┌─────────┐ ┌───────┐ │  ┌───────────────┐  │
│  │  Tools   │ │Resources│ │Prompts│ │  │ 30+ endpoints │  │
│  └────┬─────┘ └────┬────┘ └───┬───┘ │  └───────┬───────┘  │
└───────┼────────────┼──────────┼──────┴──────────┼──────────┘
        │             │             │
┌───────▼─────────────▼─────────────▼────────────────────────┐
│                 Business Logic Layer                         │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                 │
│  │  Query   │  │Validation│  │  Plugin  │                 │
│  │  Engine  │  │  Engine  │  │  System  │                 │
│  └────┬─────┘  └────┬─────┘  └────┬─────┘                 │
└───────┼─────────────┼─────────────┼────────────────────────┘
        │             │             │
┌───────▼─────────────▼─────────────▼────────────────────────┐
│                  Database Layer                             │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐                 │
│  │Supabase  │  │PostgreSQL│  │ pgvector │                 │
│  │  Client  │  │   Core   │  │ Extension│                 │
│  └──────────┘  └──────────┘  └──────────┘                 │
└─────────────────────────────────────────────────────────────┘
```

***

## Core Principles

### 1. Spec Compliance First

* **IETF vCon Core** (`draft-ietf-vcon-vcon-core-02`, v0.4.0) compliance
* Strict validation of all vCon objects
* Corrected field names (`schema` not `schema_version`, etc.)
* Required fields enforced (e.g., `vendor` in Analysis)

### 2. Type Safety

* **TypeScript** for compile-time type checking
* **Zod** for runtime validation
* Complete type definitions for all vCon objects
* No `any` types in core code

### 3. Extensibility

* **Plugin system** for custom functionality
* Lifecycle hooks at all operation points
* Custom tools and resources registration
* Minimal core, maximal flexibility

### 4. Performance

* **Efficient database** queries with proper indexing
* Vector search with HNSW indexing
* Materialized views for tag queries
* Caching strategies

### 5. Developer Experience

* Clear error messages
* Comprehensive documentation
* Example code for all features
* Testing utilities and fixtures

***

## Component Architecture

### MCP Server Layer

#### Server Initialization

```typescript
const server = new Server(
  {
    name: 'vcon-mcp-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
      resources: {},
      prompts: {},
    },
  }
);
```

The server implements three MCP interfaces:

1. **Tools** - Operations (create, read, update, delete, search)
2. **Resources** - URI-based data access (`vcon://v1/vcons/...`)
3. **Prompts** - Query templates and guidance

#### Request Flow

```
1. Client Request → stdio transport
2. MCP Protocol Parsing → JSON-RPC
3. Request Handler → Tool/Resource/Prompt
4. Plugin Hooks → beforeCreate, afterRead, etc.
5. Business Logic → Validation, queries
6. Database Operations → Supabase client
7. Response Formatting → MCP protocol
8. Plugin Hooks → afterCreate, afterUpdate, etc.
9. Response → stdio transport
```

***

### Business Logic Layer

#### Query Engine (`src/db/queries.ts`)

Handles all database operations with a focus on correctness and performance.

```typescript
export class VConQueries {
  constructor(private supabase: SupabaseClient) {}

  // CRUD operations
  async createVCon(vcon: VCon): Promise<{ uuid: string }>
  async getVCon(uuid: string): Promise<VCon>
  async updateVCon(uuid: string, updates: any): Promise<void>
  async deleteVCon(uuid: string): Promise<void>

  // Search operations
  async searchVCons(criteria: SearchCriteria): Promise<VCon[]>
  async searchVConsContent(query: string, options: SearchOptions): Promise<SearchResult[]>
  async searchVConsSemantic(query: string, options: SemanticOptions): Promise<SemanticResult[]>
  async searchVConsHybrid(query: string, options: HybridOptions): Promise<HybridResult[]>

  // Component operations
  async addDialog(vconUuid: string, dialog: Dialog): Promise<number>
  async addAnalysis(vconUuid: string, analysis: Analysis): Promise<number>
  async addAttachment(vconUuid: string, attachment: Attachment): Promise<number>

  // Tag operations
  async getTags(vconUuid: string): Promise<Record<string, string>>
  async setTag(vconUuid: string, key: string, value: string): Promise<void>
  async removeTag(vconUuid: string, key: string): Promise<void>
  async searchByTags(tags: Record<string, string>): Promise<VCon[]>
}
```

**Design Decisions:**

* **Transactional** - Uses database transactions for multi-step operations
* **Normalized** - Stores vCons in normalized form for efficient querying
* **Denormalized responses** - Returns complete vCon objects to clients
* **Error handling** - Wraps database errors with context

#### Validation Engine (`src/utils/validation.ts`)

Ensures all vCons comply with IETF spec before storage.

```typescript
export class VConValidator {
  validate(vcon: VCon): ValidationResult {
    // Core validation
    this.validateVersion(vcon)
    this.validateUUID(vcon.uuid)
    this.validateParties(vcon.parties)
    
    // Component validation
    if (vcon.dialog) this.validateDialogs(vcon.dialog)
    if (vcon.analysis) this.validateAnalysis(vcon.analysis)
    if (vcon.attachments) this.validateAttachments(vcon.attachments)
    
    // Relationship validation
    this.validateReferences(vcon)
    
    return this.result
  }
}
```

**Validation Checks:**

* ✅ vCon version is `0.4.0`
* ✅ UUID is valid RFC 4122 format
* ✅ At least one party exists
* ✅ Dialog types are valid
* ✅ Analysis has required `vendor` field
* ✅ References (party indexes, dialog indexes) are valid
* ✅ Encoding values are valid
* ✅ Dates are ISO 8601 format

#### Plugin System (`src/hooks/`)

Allows extending functionality without modifying core code.

```typescript
export interface VConPlugin {
  name: string
  version: string

  // Lifecycle
  initialize?(config: PluginConfig): Promise<void>
  shutdown?(): Promise<void>

  // Operation hooks
  beforeCreate?(vcon: VCon, context: RequestContext): Promise<VCon>
  afterCreate?(vcon: VCon, context: RequestContext): Promise<void>
  beforeRead?(uuid: string, context: RequestContext): Promise<void>
  afterRead?(vcon: VCon, context: RequestContext): Promise<VCon>
  beforeUpdate?(uuid: string, updates: any, context: RequestContext): Promise<void>
  afterUpdate?(vcon: VCon, context: RequestContext): Promise<void>
  beforeDelete?(uuid: string, context: RequestContext): Promise<void>
  afterDelete?(uuid: string, context: RequestContext): Promise<void>
  beforeSearch?(criteria: any, context: RequestContext): Promise<any>
  afterSearch?(results: VCon[], context: RequestContext): Promise<VCon[]>

  // Registration
  registerTools?(): Tool[]
  registerResources?(): Resource[]
  registerPrompts?(): Prompt[]
}
```

**Plugin Lifecycle:**

```
1. Server Start
   ↓
2. Load Plugins (from VCON_PLUGINS_PATH)
   ↓
3. Call plugin.initialize()
   ↓
4. Register tools/resources/prompts
   ↓
5. Hook into request handlers
   ↓
6. Process requests with hooks
   ↓
7. On shutdown, call plugin.shutdown()
```

***

### Database Layer

#### Schema Design

**Normalized Storage:**

```sql
vcons (main table)
  ├── parties (1:N)
  ├── dialog (1:N)
  ├── analysis (1:N)
  ├── attachments (1:N)
  │   └── tags (special attachment type)
  └── groups (1:N)
```

**Benefits:**

* Efficient querying by component
* Easy to add/remove components
* Proper foreign key constraints
* Scalable to millions of vCons

#### Supabase Client (`src/db/client.ts`)

Manages database connection with retry logic and error handling.

```typescript
let supabase: SupabaseClient | null = null

export function getSupabaseClient(): SupabaseClient {
  if (!supabase) {
    const url = process.env.SUPABASE_URL
    const key = process.env.SUPABASE_ANON_KEY
    
    if (!url || !key) {
      throw new Error('Missing Supabase credentials')
    }
    
    supabase = createClient(url, key, {
      auth: {
        persistSession: false
      },
      db: {
        schema: 'public'
      }
    })
  }
  
  return supabase
}
```

#### Search Architecture

**Three Search Modes:**

1. **Metadata Search** (`searchVCons`)
   * Filters by subject, party, dates
   * Uses B-tree indexes
   * \~50ms response time
2. **Content Search** (`searchVConsContent`)
   * Full-text search with trigram matching
   * Uses GIN indexes
   * \~100ms response time
3. **Semantic Search** (`searchVConsSemantic`)
   * Vector similarity with embeddings
   * Uses HNSW index
   * \~200ms response time
4. **Hybrid Search** (`searchVConsHybrid`)
   * Combines keyword + semantic
   * Weighted scoring
   * \~300ms response time

**Search RPC Functions:**

```sql
-- Keyword search
search_vcons_keyword(query_text, start_date, end_date, tag_filter, max_results)

-- Semantic search
search_vcons_semantic(query_embedding, tag_filter, match_threshold, match_count)

-- Hybrid search
search_vcons_hybrid(keyword_query, query_embedding, tag_filter, semantic_weight, limit_results)
```

#### Tag Management

**Storage:** Tags are stored as special attachments:

```json
{
  "type": "tags",
  "encoding": "json",
  "body": "[\"department:sales\", \"priority:high\", \"status:open\"]"
}
```

**Materialized View:**

```sql
CREATE MATERIALIZED VIEW vcon_tags_mv AS
SELECT 
  vcon_id,
  split_part(elem, ':', 1) AS key,
  split_part(elem, ':', 2) AS value
FROM attachments
CROSS JOIN LATERAL jsonb_array_elements_text(body::jsonb) AS elem
WHERE type = 'tags' AND encoding = 'json'
```

**Benefits:**

* Fast tag searches (indexed materialized view)
* No schema changes needed for new tags
* Easy to query and update
* Compatible with vCon spec (as attachments)

***

## Data Flow Examples

### Creating a vCon

```
User: "Create a vCon for a support call"
  ↓
Claude calls: create_vcon tool
  ↓
MCP Server receives request
  ↓
Plugin: beforeCreate hook (add metadata)
  ↓
Validation: Check vCon structure
  ↓
Database: Transaction starts
  ├── Insert into vcons table
  ├── Insert parties
  ├── Insert dialog (if provided)
  └── Insert analysis (if provided)
  ↓
Database: Transaction commits
  ↓
Plugin: afterCreate hook (log, webhook)
  ↓
Response: { success: true, uuid: "..." }
  ↓
Claude receives response
```

### Semantic Search

```
User: "Find frustrated customers from last week"
  ↓
Claude calls: search_vcons_semantic tool
  ↓
MCP Server receives request
  ↓
Plugin: beforeSearch hook (add tenant filter)
  ↓
Generate embedding for query
  ├── Call OpenAI API (or local model)
  └── Get 384-dimensional vector
  ↓
Database: Call search_vcons_semantic RPC
  ├── Vector similarity search (HNSW index)
  ├── Filter by tags (materialized view)
  ├── Apply threshold
  └── Order by similarity
  ↓
Reconstruct full vCon objects
  ├── Join with parties table
  ├── Join with dialog table
  └── Join with analysis table
  ↓
Plugin: afterSearch hook (filter sensitive)
  ↓
Response: { count: N, results: [...] }
  ↓
Claude receives results
```

***

## Performance Considerations

### Database Optimization

1. **Indexes**
   * B-tree on UUIDs, dates
   * GIN on text fields (trigram)
   * HNSW on embeddings (vector)
   * Composite indexes on common queries
2. **Query Patterns**
   * Use prepared statements
   * Batch operations where possible
   * Limit result sets
   * Use cursors for large result sets
3. **Caching**
   * Materialize frequently accessed views
   * Cache embeddings
   * Use connection pooling

### Memory Management

* Streaming large responses
* Limit result set sizes
* Clean up plugin resources
* Close database connections properly

### Scalability

**Horizontal Scaling:**

* Stateless server design
* Multiple server instances behind load balancer
* Read replicas for queries

**Vertical Scaling:**

* Increase database resources
* Optimize queries and indexes
* Use faster embedding models

***

## Security Architecture

### Authentication

* Supabase Row Level Security (RLS)
* API key validation
* User context in plugin hooks

### Authorization

* RLS policies on all tables
* Plugin-based access control
* Audit logging via plugins

### Data Protection

* Encryption at rest (Supabase)
* Encryption in transit (TLS)
* Redaction via plugins
* PII handling compliance

***

## Testing Architecture

### Unit Tests

* Individual function testing
* Mocked dependencies
* Zod schema validation

### Integration Tests

* Full request/response cycle
* Real database (test instance)
* Plugin integration

### Compliance Tests

* IETF spec validation
* Field name correctness
* Required field enforcement

### Load Tests

* Concurrent requests
* Large result sets
* Search performance

***

## Deployment Architecture

### Development

```
Local Machine
├── Node.js runtime
├── TypeScript compiler
├── Supabase local (Docker)
└── Environment variables
```

### Production

```
Cloud Provider (AWS, GCP, Azure)
├── Node.js runtime (18+)
├── Process manager (PM2, systemd)
├── Reverse proxy (nginx)
├── SSL termination
└── Supabase managed instance
```

### Monitoring

* Health check endpoint
* Performance metrics
* Error tracking
* Query performance

***

## Extension Points

### Adding New Tools

1. Define tool schema (`src/tools/`)
2. Implement handler in server
3. Add validation
4. Write tests
5. Document in API reference

### Adding New Search Modes

1. Create RPC function in database
2. Add method to VConQueries
3. Create MCP tool definition
4. Implement in tool handler
5. Add performance tests

### Creating Plugins

1. Implement VConPlugin interface
2. Register lifecycle hooks
3. Add custom tools/resources
4. Package as npm module
5. Publish and document

***

## Best Practices

### Code Organization

* One tool per file
* Shared types in `types/`
* Database logic in `db/`
* Utilities in `utils/`
* Tests alongside code

### Error Handling

* Use typed errors
* Provide context
* Log errors properly
* Return user-friendly messages

### Performance

* Profile before optimizing
* Use indexes effectively
* Cache when appropriate
* Monitor query performance

### Documentation

* JSDoc for all public APIs
* README for each directory
* Architecture decisions recorded
* Examples for complex features

***

## Future Architecture

### Planned Enhancements

1. **Streaming Responses** - For large result sets
2. **GraphQL API** - Alternative to RPC
3. **Real-time Subscriptions** - WebSocket support
4. **Distributed Tracing** - OpenTelemetry integration
5. **Multi-tenant** - Tenant isolation patterns

***

## Additional Resources

* [IETF vCon Spec](https://datatracker.ietf.org/doc/html/draft-ietf-vcon-vcon-core-02)
* [MCP Protocol](https://modelcontextprotocol.io/)
* [Supabase Architecture](https://supabase.com/docs/guides/platform/architecture)
* [pgvector](https://github.com/pgvector/pgvector)
* [TypeScript Best Practices](https://google.github.io/styleguide/tsguide.html)


# Building from Source

> **Complete guide to building an IETF vCon-compliant MCP Server from scratch**

## 📋 Table of Contents

1. [Prerequisites](#prerequisites)
2. [Project Overview](#project-overview)
3. [Phase 1: Environment Setup](#phase-1-environment-setup)
4. [Phase 2: Database Setup](#phase-2-database-setup)
5. [Phase 3: Project Structure](#phase-3-project-structure)
6. [Phase 4: Core Implementation](#phase-4-core-implementation)
7. [Phase 5: MCP Server](#phase-5-mcp-server)
8. [Phase 6: Testing & Validation](#phase-6-testing--validation)
9. [Phase 7: Deployment](#phase-7-deployment)
10. [Troubleshooting](#troubleshooting)
11. [Next Steps](#next-steps)

***

## Prerequisites

### Required Knowledge

* ✅ TypeScript/JavaScript programming
* ✅ Node.js and npm/yarn
* ✅ PostgreSQL basics
* ✅ REST APIs and JSON
* ✅ Git version control

### Required Software

* ✅ **Node.js** 18.x or higher ([Download](https://nodejs.org/))
* ✅ **npm** or **yarn** package manager
* ✅ **Git** ([Download](https://git-scm.com/))
* ✅ **Code editor** (VS Code recommended)
* ✅ **Supabase account** ([Sign up](https://supabase.com/))

### Time Estimate

* **Total:** 4-6 hours for first-time implementation
* **Experienced developers:** 2-3 hours

***

## Project Overview

### What We're Building

An **MCP (Model Context Protocol) Server** that:

* Stores and manages IETF vCon (Virtual Conversation) data
* Provides tools for AI assistants to interact with vCons
* Ensures full compliance with `draft-ietf-vcon-vcon-core-02`
* Uses Supabase (PostgreSQL) as the database backend

### Key Features

* ✅ Create, read, update, delete vCons
* ✅ Add dialog, analysis, and attachments
* ✅ Search and query vCon data
* ✅ Privacy and consent management
* ✅ Spec-compliant data validation
* ✅ MCP tools for AI integration

### Architecture

```
┌─────────────────┐
│   AI Assistant  │ (Claude, etc.)
└────────┬────────┘
         │ MCP Protocol
┌────────▼────────┐
│   MCP Server    │ (This project)
└────────┬────────┘
         │ Supabase Client
┌────────▼────────┐
│    Supabase     │ (PostgreSQL + REST API)
└─────────────────┘
```

***

## Phase 1: Environment Setup

### Step 1.1: Create Project Directory

```bash
# Create project directory
mkdir vcon-mcp-server
cd vcon-mcp-server

# Initialize git repository
git init
```

### Step 1.2: Initialize Node.js Project

```bash
# Create package.json
npm init -y
```

### Step 1.3: Install Dependencies

```bash
# Core dependencies
npm install @modelcontextprotocol/sdk @supabase/supabase-js zod

# Development dependencies
npm install -D typescript @types/node tsx vitest eslint \
  @typescript-eslint/eslint-plugin @typescript-eslint/parser
```

**What each package does:**

* `@modelcontextprotocol/sdk` - MCP server framework
* `@supabase/supabase-js` - Supabase client library
* `zod` - Schema validation library
* `typescript` - TypeScript compiler
* `tsx` - TypeScript execution for development
* `vitest` - Testing framework

### Step 1.4: Configure TypeScript

Create `tsconfig.json`:

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "lib": ["ES2022"],
    "outDir": "./dist",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,
    "moduleResolution": "bundler",
    "resolveJsonModule": true,
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "tests"]
}
```

### Step 1.5: Update package.json Scripts

Add these scripts to your `package.json`:

```json
{
  "type": "module",
  "scripts": {
    "build": "tsc",
    "dev": "tsx watch src/index.ts",
    "test": "vitest",
    "test:compliance": "vitest run tests/vcon-compliance.test.ts",
    "lint": "eslint src/**/*.ts"
  }
}
```

### Step 1.6: Create .env.example

Create `.env.example`:

```bash
# Supabase Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key-here

# Optional: For service role operations
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
```

### Step 1.7: Create .gitignore

Create `.gitignore`:

```
# Node
node_modules/
npm-debug.log*
package-lock.json

# TypeScript
dist/
*.tsbuildinfo

# Environment variables
.env
.env.local

# IDE
.vscode/
.idea/
.DS_Store

# Testing
coverage/

# Logs
*.log
```

### ✅ Phase 1 Checkpoint

Verify your setup:

```bash
# Check Node.js version
node --version  # Should be 18.x or higher

# Check TypeScript
npx tsc --version

# Verify package.json
cat package.json

# Check dependencies
npm list
```

***

## Phase 2: Database Setup

### Step 2.1: Create Supabase Project

1. Go to [supabase.com](https://supabase.com/)
2. Click "New Project"
3. Fill in:
   * **Name:** vcon-mcp-server
   * **Database Password:** (Generate strong password)
   * **Region:** (Choose closest to you)
4. Click "Create new project"
5. Wait 2-3 minutes for provisioning

### Step 2.2: Get Supabase Credentials

1. Go to Project Settings → API
2. Copy:
   * **Project URL** → SUPABASE\_URL
   * **anon/public key** → SUPABASE\_ANON\_KEY

Create `.env` file:

```bash
SUPABASE_URL=https://xxxxxxxxxxxxx.supabase.co
SUPABASE_ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```

### Step 2.3: Run Database Schema

1. Go to SQL Editor in Supabase dashboard
2. Copy the entire schema from `CORRECTED_SCHEMA.md`
3. Paste into SQL Editor
4. Click "Run" to execute

**Key tables created:**

* `vcons` - Main vCon records
* `parties` - Conversation participants
* `dialog` - Conversation content (recordings, text, etc.)
* `analysis` - AI/ML analysis results
* `attachments` - File attachments
* `party_history` - Party event timeline

### Step 2.4: Verify Database Schema

Run these verification queries in SQL Editor:

```sql
-- Check tables exist
SELECT tablename FROM pg_tables 
WHERE schemaname = 'public'
ORDER BY tablename;

-- Check analysis table has 'schema' field (not 'schema_version')
SELECT column_name, data_type, is_nullable 
FROM information_schema.columns
WHERE table_name = 'analysis'
ORDER BY ordinal_position;

-- Verify vendor is NOT NULL
SELECT column_name, is_nullable
FROM information_schema.columns
WHERE table_name = 'analysis' 
AND column_name = 'vendor';
-- Should show 'NO' for is_nullable

-- Verify dialog type constraint exists
SELECT constraint_name, check_clause
FROM information_schema.check_constraints
WHERE constraint_name = 'dialog_type_check';

-- Check that encoding fields have no default values
SELECT column_name, column_default
FROM information_schema.columns
WHERE table_name IN ('dialog', 'analysis', 'attachments')
AND column_name = 'encoding';
-- All should show NULL for column_default
```

**Expected results:**

* ✅ 8+ tables created
* ✅ `analysis.schema` exists (NOT `schema_version`)
* ✅ `analysis.vendor` is NOT NULL
* ✅ `analysis.body` is TEXT type
* ✅ No DEFAULT values on encoding fields
* ✅ Dialog type constraint exists

### Step 2.5: Set Up Row Level Security (Optional)

For multi-tenant applications, enable RLS:

```sql
-- Enable RLS on all tables
ALTER TABLE vcons ENABLE ROW LEVEL SECURITY;
ALTER TABLE parties ENABLE ROW LEVEL SECURITY;
ALTER TABLE dialog ENABLE ROW LEVEL SECURITY;
ALTER TABLE analysis ENABLE ROW LEVEL SECURITY;
ALTER TABLE attachments ENABLE ROW LEVEL SECURITY;

-- Example policy: Users can only access their own vCons
CREATE POLICY "Users can view own vcons"
  ON vcons FOR SELECT
  USING (auth.uid() = user_id);

CREATE POLICY "Users can create own vcons"
  ON vcons FOR INSERT
  WITH CHECK (auth.uid() = user_id);
```

### ✅ Phase 2 Checkpoint

Verify database setup:

```bash
# Test connection with a simple query
node -e "
import { createClient } from '@supabase/supabase-js';
const supabase = createClient(
  process.env.SUPABASE_URL,
  process.env.SUPABASE_ANON_KEY
);
const { data, error } = await supabase.from('vcons').select('count');
console.log('Connection test:', error ? 'FAILED' : 'SUCCESS');
"
```

***

## Phase 3: Project Structure

### Step 3.1: Create Directory Structure

```bash
# Create all directories
mkdir -p src/{types,tools,resources,prompts,db,utils}
mkdir -p tests
mkdir -p scripts
```

### Step 3.2: Verify Structure

Your project should now look like this:

```
vcon-mcp-server/
├── src/
│   ├── types/          # TypeScript type definitions
│   ├── tools/          # MCP tool implementations
│   ├── resources/      # MCP resource handlers
│   ├── prompts/        # MCP prompt templates
│   ├── db/            # Database client and queries
│   └── utils/         # Utility functions
├── tests/             # Test files
├── scripts/           # Build and maintenance scripts
├── package.json
├── tsconfig.json
├── .env
├── .env.example
└── .gitignore
```

### ✅ Phase 3 Checkpoint

```bash
# Verify directory structure
ls -R src/
```

***

## Phase 4: Core Implementation

### Step 4.1: Create vCon Types

Create `src/types/vcon.ts`:

```typescript
/**
 * IETF vCon Core Types - Compliant with draft-ietf-vcon-vcon-core-02
 * CRITICAL: Uses corrected field names per specification
 */

export type VConVersion = '0.4.0';
export type Encoding = 'base64url' | 'json' | 'none';
export type DialogType = 'recording' | 'text' | 'transfer' | 'incomplete';

// Section 4.2 - Party Object
export interface Party {
  tel?: string;
  sip?: string;
  stir?: string;
  mailto?: string;
  name?: string;
  did?: string;
  validation?: string;
  jcard?: object;
  gmlpos?: string;
  civicaddress?: object;
  timezone?: string;
  uuid?: string;  // Section 4.2.12 - REQUIRED FIELD
}

// Section 4.3 - Dialog Object
export interface Dialog {
  type: DialogType;
  start?: string;
  duration?: number;
  parties?: number | number[] | (number | number[])[];
  originator?: number;
  mediatype?: string;
  filename?: string;
  body?: string;
  encoding?: Encoding;
  url?: string;
  content_hash?: string | string[];
  disposition?: 'no-answer' | 'congestion' | 'failed' | 'busy' | 'hung-up' | 'voicemail-no-message';
  session_id?: string;      // Section 4.3.10
  application?: string;     // Section 4.3.13
  message_id?: string;      // Section 4.3.14
}

// Section 4.5 - Analysis Object
// ⚠️ CRITICAL: This is the CORRECTED version
export interface Analysis {
  type: string;
  dialog?: number | number[];
  mediatype?: string;
  filename?: string;
  vendor: string;        // ✅ REQUIRED per spec Section 4.5.5
  product?: string;
  schema?: string;       // ✅ CORRECT: Not 'schema_version'
  body?: string;         // ✅ CORRECT: String, not object
  encoding?: Encoding;
  url?: string;
  content_hash?: string | string[];
}

// Section 4.4 - Attachment Object
export interface Attachment {
  type?: string;
  start?: string;
  party?: number;
  dialog?: number;
  mediatype?: string;
  filename?: string;
  body?: string;
  encoding?: Encoding;
  url?: string;
  content_hash?: string | string[];
}

// Section 4.1 - Main vCon Object
export interface VCon {
  vcon: VConVersion;
  uuid: string;
  extensions?: string[];      // Section 4.1.3
  critical?: string[];        // Section 4.1.4 (renamed from "must_support" in v0.4.0)
  created_at: string;
  updated_at?: string;
  subject?: string;
  redacted?: {
    uuid?: string;
    type?: string;
    url?: string;
    content_hash?: string | string[];
  };
  amended?: {                 // Renamed from "appended" in v0.4.0
    uuid?: string;
    url?: string;
    content_hash?: string | string[];
  };
  group?: Array<{
    uuid?: string;
    body?: string;
    encoding?: 'json';
    url?: string;
    content_hash?: string | string[];
  }>;
  parties: Party[];
  dialog?: Dialog[];
  analysis?: Analysis[];
  attachments?: Attachment[];
}

// Validation helper functions
export function isValidDialogType(type: string): type is DialogType {
  return ['recording', 'text', 'transfer', 'incomplete'].includes(type);
}

export function isValidEncoding(encoding: string): encoding is Encoding {
  return ['base64url', 'json', 'none'].includes(encoding);
}
```

**💡 Key Points:**

* ✅ Uses `schema` not `schema_version` in Analysis
* ✅ `vendor` is required (no `?`) in Analysis
* ✅ `body` is `string` type (not `object`)
* ✅ Includes `uuid` field in Party
* ✅ Includes new fields: `session_id`, `application`, `message_id`

### Step 4.2: Create Database Client

Create `src/db/client.ts`:

```typescript
import { createClient, SupabaseClient } from '@supabase/supabase-js';

let supabase: SupabaseClient | null = null;

export function getSupabaseClient(): SupabaseClient {
  if (!supabase) {
    const url = process.env.SUPABASE_URL;
    const key = process.env.SUPABASE_ANON_KEY;

    if (!url || !key) {
      throw new Error(
        'Missing Supabase credentials. Set SUPABASE_URL and SUPABASE_ANON_KEY environment variables.'
      );
    }

    supabase = createClient(url, key);
  }

  return supabase;
}

export function closeSupabaseClient(): void {
  supabase = null;
}
```

### Step 4.3: Create Database Queries

Create `src/db/queries.ts`:

```typescript
import { SupabaseClient } from '@supabase/supabase-js';
import { VCon, Analysis, Dialog, Party } from '../types/vcon';

export class VConQueries {
  constructor(private supabase: SupabaseClient) {}

  async createVCon(vcon: VCon): Promise<{ uuid: string }> {
    // Insert main vcon
    const { data: vconData, error: vconError } = await this.supabase
      .from('vcons')
      .insert({
        uuid: vcon.uuid,
        vcon_version: vcon.vcon,
        subject: vcon.subject,
        created_at: vcon.created_at,
        updated_at: vcon.updated_at,
        extensions: vcon.extensions,
        critical: vcon.critical,
      })
      .select('id, uuid')
      .single();

    if (vconError) throw vconError;

    // Insert parties
    if (vcon.parties.length > 0) {
      const partiesData = vcon.parties.map((party, index) => ({
        vcon_id: vconData.id,
        party_index: index,
        tel: party.tel,
        sip: party.sip,
        mailto: party.mailto,
        name: party.name,
        did: party.did,
        uuid: party.uuid,  // ✅ Corrected field
        validation: party.validation,
      }));

      const { error: partiesError } = await this.supabase
        .from('parties')
        .insert(partiesData);

      if (partiesError) throw partiesError;
    }

    return { uuid: vconData.uuid };
  }

  async addAnalysis(vconUuid: string, analysis: Analysis): Promise<void> {
    const { data: vcon, error: vconError } = await this.supabase
      .from('vcons')
      .select('id')
      .eq('uuid', vconUuid)
      .single();

    if (vconError) throw vconError;

    // Get next analysis index
    const { data: existingAnalysis } = await this.supabase
      .from('analysis')
      .select('analysis_index')
      .eq('vcon_id', vcon.id)
      .order('analysis_index', { ascending: false })
      .limit(1);

    const nextIndex = existingAnalysis?.length 
      ? existingAnalysis[0].analysis_index + 1 
      : 0;

    // ✅ CORRECTED: Use 'schema' not 'schema_version'
    const { error: analysisError } = await this.supabase
      .from('analysis')
      .insert({
        vcon_id: vcon.id,
        analysis_index: nextIndex,
        type: analysis.type,
        dialog_indices: Array.isArray(analysis.dialog) 
          ? analysis.dialog 
          : (analysis.dialog ? [analysis.dialog] : null),
        mediatype: analysis.mediatype,
        filename: analysis.filename,
        vendor: analysis.vendor,    // ✅ REQUIRED field
        product: analysis.product,
        schema: analysis.schema,    // ✅ Correct field name
        body: analysis.body,        // ✅ TEXT type
        encoding: analysis.encoding,
        url: analysis.url,
        content_hash: analysis.content_hash,
      });

    if (analysisError) throw analysisError;
  }

  async getVCon(uuid: string): Promise<VCon> {
    // Get main vcon
    const { data: vconData, error: vconError } = await this.supabase
      .from('vcons')
      .select('*')
      .eq('uuid', uuid)
      .single();

    if (vconError) throw vconError;

    // Get parties
    const { data: parties } = await this.supabase
      .from('parties')
      .select('*')
      .eq('vcon_id', vconData.id)
      .order('party_index');

    // Get dialog
    const { data: dialogs } = await this.supabase
      .from('dialog')
      .select('*')
      .eq('vcon_id', vconData.id)
      .order('dialog_index');

    // Get analysis - ✅ Queries 'schema' not 'schema_version'
    const { data: analysis } = await this.supabase
      .from('analysis')
      .select('*')
      .eq('vcon_id', vconData.id)
      .order('analysis_index');

    // Reconstruct vCon
    return {
      vcon: vconData.vcon_version as '0.4.0',
      uuid: vconData.uuid,
      extensions: vconData.extensions,
      critical: vconData.critical,
      created_at: vconData.created_at,
      updated_at: vconData.updated_at,
      subject: vconData.subject,
      parties: parties?.map(p => ({
        tel: p.tel,
        sip: p.sip,
        mailto: p.mailto,
        name: p.name,
        did: p.did,
        uuid: p.uuid,
        validation: p.validation,
      })) || [],
      dialog: dialogs?.map(d => ({
        type: d.type,
        start: d.start_time,
        duration: d.duration_seconds,
        parties: d.parties,
        originator: d.originator,
        mediatype: d.mediatype,
        body: d.body,
        encoding: d.encoding,
        session_id: d.session_id,
        application: d.application,
        message_id: d.message_id,
      })),
      analysis: analysis?.map(a => ({
        type: a.type,
        dialog: a.dialog_indices,
        vendor: a.vendor,
        product: a.product,
        schema: a.schema,  // ✅ Correct field name
        body: a.body,
        encoding: a.encoding,
      })),
    };
  }

  async searchVCons(filters: {
    subject?: string;
    partyName?: string;
    startDate?: string;
    endDate?: string;
  }): Promise<VCon[]> {
    let query = this.supabase
      .from('vcons')
      .select('*');

    if (filters.subject) {
      query = query.ilike('subject', `%${filters.subject}%`);
    }

    if (filters.startDate) {
      query = query.gte('created_at', filters.startDate);
    }

    if (filters.endDate) {
      query = query.lte('created_at', filters.endDate);
    }

    const { data, error } = await query;
    if (error) throw error;

    // Fetch full vCons for results
    return Promise.all(
      data.map(v => this.getVCon(v.uuid))
    );
  }
}
```

### Step 4.4: Create Validation Utilities

Create `src/utils/validation.ts`:

```typescript
import { VCon, Analysis, Dialog } from '../types/vcon';

export class VConValidator {
  private errors: string[] = [];

  validate(vcon: VCon): { valid: boolean; errors: string[] } {
    this.errors = [];

    this.validateVersion(vcon);
    this.validateUUID(vcon.uuid);
    this.validateParties(vcon.parties);
    if (vcon.dialog) this.validateDialogs(vcon.dialog);
    if (vcon.analysis) this.validateAnalysis(vcon.analysis);

    return {
      valid: this.errors.length === 0,
      errors: this.errors
    };
  }

  private validateVersion(vcon: VCon): void {
    if (vcon.vcon !== '0.4.0') {
      this.errors.push(`Invalid vcon version: ${vcon.vcon}`);
    }
  }

  private validateUUID(uuid: string): void {
    const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
    if (!uuidRegex.test(uuid)) {
      this.errors.push(`Invalid UUID format: ${uuid}`);
    }
  }

  private validateParties(parties: any[]): void {
    if (parties.length === 0) {
      this.errors.push('vCon must have at least one party');
    }
  }

  private validateDialogs(dialogs: Dialog[]): void {
    dialogs.forEach((dialog, i) => {
      const validTypes = ['recording', 'text', 'transfer', 'incomplete'];
      if (!validTypes.includes(dialog.type)) {
        this.errors.push(`Dialog ${i} has invalid type: ${dialog.type}`);
      }
    });
  }

  private validateAnalysis(analyses: Analysis[]): void {
    analyses.forEach((analysis, i) => {
      // ✅ CRITICAL: vendor is required
      if (!analysis.vendor) {
        this.errors.push(`Analysis ${i} missing required field: vendor`);
      }
    });
  }
}

export function validateVCon(vcon: VCon) {
  return new VConValidator().validate(vcon);
}
```

### ✅ Phase 4 Checkpoint

Verify your implementation:

```bash
# Compile TypeScript
npm run build

# Should compile without errors
# Check dist/ directory was created
ls dist/
```

***

## Phase 5: MCP Server

### Step 5.1: Create MCP Tool Definitions

Create `src/tools/vcon-crud.ts`:

```typescript
import { z } from 'zod';

// ✅ CORRECTED: Analysis schema with proper field names
export const AnalysisSchema = z.object({
  type: z.string(),
  dialog: z.union([z.number(), z.array(z.number())]).optional(),
  vendor: z.string(),              // ✅ REQUIRED
  product: z.string().optional(),
  schema: z.string().optional(),   // ✅ Correct field name
  body: z.string().optional(),     // ✅ String type
  encoding: z.enum(['base64url', 'json', 'none']).optional(),
});

export const PartySchema = z.object({
  tel: z.string().optional(),
  mailto: z.string().optional(),
  name: z.string().optional(),
  uuid: z.string().uuid().optional(),  // ✅ Added
});

export const DialogSchema = z.object({
  type: z.enum(['recording', 'text', 'transfer', 'incomplete']),
  start: z.string().optional(),
  body: z.string().optional(),
  encoding: z.enum(['base64url', 'json', 'none']).optional(),
  session_id: z.string().optional(),
  application: z.string().optional(),
  message_id: z.string().optional(),
});

// MCP Tool: Create vCon
export const createVConTool = {
  name: 'create_vcon',
  description: 'Create a new vCon compliant with IETF spec',
  inputSchema: {
    type: 'object',
    properties: {
      subject: { type: 'string' },
      parties: {
        type: 'array',
        items: {
          type: 'object',
          properties: {
            name: { type: 'string' },
            tel: { type: 'string' },
            mailto: { type: 'string' },
            uuid: { type: 'string' },
          }
        },
        minItems: 1
      }
    },
    required: ['parties']
  }
};

// MCP Tool: Add Analysis
export const addAnalysisTool = {
  name: 'add_analysis',
  description: 'Add analysis to a vCon',
  inputSchema: {
    type: 'object',
    properties: {
      vcon_uuid: { type: 'string', format: 'uuid' },
      analysis: {
        type: 'object',
        properties: {
          type: { type: 'string' },
          vendor: { type: 'string' },    // ✅ REQUIRED
          product: { type: 'string' },
          schema: { type: 'string' },    // ✅ Correct name
          body: { type: 'string' },      // ✅ String type
          encoding: {
            type: 'string',
            enum: ['base64url', 'json', 'none']
          }
        },
        required: ['type', 'vendor']     // ✅ vendor required
      }
    },
    required: ['vcon_uuid', 'analysis']
  }
};

// MCP Tool: Get vCon
export const getVConTool = {
  name: 'get_vcon',
  description: 'Retrieve a vCon by UUID',
  inputSchema: {
    type: 'object',
    properties: {
      uuid: { type: 'string', format: 'uuid' }
    },
    required: ['uuid']
  }
};

// MCP Tool: Search vCons
export const searchVConsTool = {
  name: 'search_vcons',
  description: 'Search vCons by criteria',
  inputSchema: {
    type: 'object',
    properties: {
      subject: { type: 'string' },
      party_name: { type: 'string' },
      start_date: { type: 'string', format: 'date-time' },
      end_date: { type: 'string', format: 'date-time' }
    }
  }
};
```

### Step 5.2: Create MCP Server

Create `src/index.ts`:

```typescript
#!/usr/bin/env node

import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
  CallToolRequestSchema,
  ListToolsRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';
import { getSupabaseClient } from './db/client.js';
import { VConQueries } from './db/queries.js';
import { validateVCon } from './utils/validation.js';
import {
  createVConTool,
  addAnalysisTool,
  getVConTool,
  searchVConsTool,
} from './tools/vcon-crud.js';
import { VCon, Analysis } from './types/vcon.js';

// Initialize MCP server
const server = new Server(
  {
    name: 'vcon-mcp-server',
    version: '1.0.0',
  },
  {
    capabilities: {
      tools: {},
    },
  }
);

// Initialize database
const supabase = getSupabaseClient();
const queries = new VConQueries(supabase);

// List available tools
server.setRequestHandler(ListToolsRequestSchema, async () => {
  return {
    tools: [
      createVConTool,
      addAnalysisTool,
      getVConTool,
      searchVConsTool,
    ],
  };
});

// Handle tool calls
server.setRequestHandler(CallToolRequestSchema, async (request) => {
  const { name, arguments: args } = request.params;

  try {
    switch (name) {
      case 'create_vcon': {
        const vcon: VCon = {
          vcon: '0.4.0',
          uuid: crypto.randomUUID(),
          created_at: new Date().toISOString(),
          subject: args.subject,
          parties: args.parties,
        };

        // Validate before saving
        const validation = validateVCon(vcon);
        if (!validation.valid) {
          return {
            content: [{
              type: 'text',
              text: `Validation failed: ${validation.errors.join(', ')}`,
            }],
            isError: true,
          };
        }

        const result = await queries.createVCon(vcon);
        return {
          content: [{
            type: 'text',
            text: `Created vCon with UUID: ${result.uuid}`,
          }],
        };
      }

      case 'add_analysis': {
        const analysis: Analysis = args.analysis;
        
        // ✅ Ensure vendor is provided
        if (!analysis.vendor) {
          return {
            content: [{
              type: 'text',
              text: 'Error: vendor is required in analysis',
            }],
            isError: true,
          };
        }

        await queries.addAnalysis(args.vcon_uuid, analysis);
        return {
          content: [{
            type: 'text',
            text: `Added analysis to vCon ${args.vcon_uuid}`,
          }],
        };
      }

      case 'get_vcon': {
        const vcon = await queries.getVCon(args.uuid);
        return {
          content: [{
            type: 'text',
            text: JSON.stringify(vcon, null, 2),
          }],
        };
      }

      case 'search_vcons': {
        const results = await queries.searchVCons({
          subject: args.subject,
          partyName: args.party_name,
          startDate: args.start_date,
          endDate: args.end_date,
        });
        return {
          content: [{
            type: 'text',
            text: JSON.stringify(results, null, 2),
          }],
        };
      }

      default:
        throw new Error(`Unknown tool: ${name}`);
    }
  } catch (error) {
    return {
      content: [{
        type: 'text',
        text: `Error: ${error.message}`,
      }],
      isError: true,
    };
  }
});

// Start server
async function main() {
  const transport = new StdioServerTransport();
  await server.connect(transport);
  console.error('vCon MCP Server running on stdio');
}

main().catch((error) => {
  console.error('Fatal error:', error);
  process.exit(1);
});
```

### Step 5.3: Test the Server

```bash
# Run in development mode
npm run dev

# In another terminal, test with MCP Inspector
npm run test:console
```

### ✅ Phase 5 Checkpoint

The server should:

* ✅ Start without errors
* ✅ List 4 tools (create, add\_analysis, get, search)
* ✅ Accept tool calls
* ✅ Return proper responses

***

## Phase 6: Testing & Validation

### Step 6.1: Create Compliance Tests

Create `tests/vcon-compliance.test.ts`:

```typescript
import { describe, it, expect } from 'vitest';
import { VCon, Analysis } from '../src/types/vcon';
import { validateVCon } from '../src/utils/validation';

describe('IETF vCon Spec Compliance', () => {
  it('should use "schema" not "schema_version"', () => {
    const analysis: Analysis = {
      type: 'test',
      vendor: 'TestVendor',
      schema: 'v1.0',  // ✅ Correct
      body: 'test',
      encoding: 'none'
    };

    expect(analysis.schema).toBe('v1.0');
    expect((analysis as any).schema_version).toBeUndefined();
  });

  it('should require vendor in analysis', () => {
    const vcon: VCon = {
      vcon: '0.4.0',
      uuid: crypto.randomUUID(),
      created_at: new Date().toISOString(),
      parties: [{ name: 'Test' }],
      analysis: [{
        type: 'test',
        body: 'test',
        encoding: 'none'
      } as any]
    };

    const result = validateVCon(vcon);
    expect(result.valid).toBe(false);
    expect(result.errors.some(e => e.includes('vendor'))).toBe(true);
  });

  it('should accept string body in analysis', () => {
    const analysis: Analysis = {
      type: 'transcript',
      vendor: 'TestVendor',
      body: 'Plain text content',  // ✅ String
      encoding: 'none'
    };

    expect(typeof analysis.body).toBe('string');
  });

  it('should support party uuid field', () => {
    const vcon: VCon = {
      vcon: '0.4.0',
      uuid: crypto.randomUUID(),
      created_at: new Date().toISOString(),
      parties: [{
        name: 'Test',
        uuid: crypto.randomUUID()  // ✅ uuid field
      }]
    };

    expect(vcon.parties[0].uuid).toBeDefined();
    expect(validateVCon(vcon).valid).toBe(true);
  });
});
```

### Step 6.2: Run Tests

```bash
# Run all tests
npm test

# Run compliance tests only
npm run test:compliance
```

### Step 6.3: Verify No Incorrect Field Names

```bash
# Search for incorrect field names in code
grep -r "schema_version" src/
# Should return NO results

grep -r "vendor?" src/types/
# Should return NO results (vendor should not be optional)
```

### ✅ Phase 6 Checkpoint

All tests should pass:

* ✅ No `schema_version` in codebase
* ✅ `vendor` is required in Analysis type
* ✅ `body` accepts string values
* ✅ All validation tests pass

***

## Phase 7: Deployment

### Step 7.1: Build for Production

```bash
# Clean and build
rm -rf dist/
npm run build

# Verify build
ls dist/
```

### Step 7.2: Configure MCP Client

Add to your MCP client configuration (e.g., Claude Desktop):

**macOS:** `~/Library/Application Support/Claude/claude_desktop_config.json` **Windows:** `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "vcon": {
      "command": "node",
      "args": ["/absolute/path/to/vcon-mcp-server/dist/index.js"],
      "env": {
        "SUPABASE_URL": "https://xxxxx.supabase.co",
        "SUPABASE_ANON_KEY": "eyJhbGciOiJIUzI1NiI..."
      }
    }
  }
}
```

### Step 7.3: Test with AI Assistant

Restart your AI assistant and try:

```
Create a new vCon with parties Alice and Bob
```

### ✅ Phase 7 Checkpoint

The AI should:

* ✅ See the vCon tools
* ✅ Successfully create vCons
* ✅ Add analysis with correct field names
* ✅ Retrieve and search vCons

***

## Troubleshooting

### Issue: TypeScript Compilation Errors

**Symptom:** Errors about missing types or incorrect field names

**Solution:**

```bash
# Reinstall dependencies
rm -rf node_modules package-lock.json
npm install

# Check TypeScript version
npx tsc --version  # Should be 5.x

# Verify tsconfig.json is correct
cat tsconfig.json
```

### Issue: Database Connection Fails

**Symptom:** "Missing Supabase credentials" error

**Solution:**

```bash
# Verify .env file exists and has correct values
cat .env

# Test connection
node -e "
require('dotenv').config();
console.log('URL:', process.env.SUPABASE_URL ? '✓' : '✗');
console.log('KEY:', process.env.SUPABASE_ANON_KEY ? '✓' : '✗');
"
```

### Issue: "schema\_version does not exist" Error

**Symptom:** Database error about unknown column

**Solution:**

```sql
-- Verify database schema is correct
SELECT column_name FROM information_schema.columns
WHERE table_name = 'analysis';

-- Should show 'schema' NOT 'schema_version'
```

If incorrect, re-run the corrected schema from `CORRECTED_SCHEMA.md`.

### Issue: Vendor Validation Fails

**Symptom:** "vendor is required" error

**Solution:**

* ✅ Always include `vendor` in analysis objects
* ✅ Check that Analysis type doesn't have `vendor?` (with question mark)
* ✅ Verify tool schema marks vendor as required

### Issue: MCP Server Doesn't Start

**Symptom:** Server crashes on startup

**Solution:**

```bash
# Check for syntax errors
npm run build

# Run with detailed logging
NODE_ENV=development npm run dev

# Verify MCP SDK version
npm list @modelcontextprotocol/sdk
```

***

## Next Steps

### Enhancements to Consider

1. **Add More Tools**
   * Update vCon
   * Delete vCon
   * Add dialog
   * Add attachments
   * Export vCon to JWS/JWE
2. **Add Resources**
   * `vcon://v1/vcons` URI scheme
   * List recent vCons
   * vCon templates
3. **Add Prompts**
   * Summarize conversation
   * Extract action items
   * Compliance check
4. **Advanced Features**
   * Privacy redaction
   * Consent management
   * Group vCons
   * Digital signatures (JWS)
   * Encryption (JWE)
5. **Performance**
   * Caching layer
   * Batch operations
   * Pagination
   * Indexes optimization
6. **Security**
   * Row Level Security
   * API rate limiting
   * Input sanitization
   * Audit logging

### Learning Resources

* **IETF vCon Spec:** `background_docs/draft-ietf-vcon-vcon-core-02.txt`
* **MCP Documentation:** <https://modelcontextprotocol.io/>
* **Supabase Docs:** <https://supabase.com/docs>
* **Implementation Guide:** `CLAUDE.md`
* **Quick Reference:** `QUICK_REFERENCE.md`

### Community & Support

* **vCon Working Group:** <https://datatracker.ietf.org/wg/vcon/>
* **MCP Discord:** <https://discord.gg/modelcontextprotocol>
* **Issues:** File bugs/questions in your repo issues

***

## Appendix: Command Reference

### Development Commands

```bash
# Install dependencies
npm install

# Build project
npm run build

# Run in development
npm run dev

# Run tests
npm test
npm run test:compliance

# Lint code
npm run lint

# Type check
npx tsc --noEmit
```

### Git Commands

```bash
# Initialize repo
git init

# Add all files
git add -A

# Commit
git commit -m "Initial commit"

# Create remote and push
git remote add origin <url>
git push -u origin main
```

### Database Commands

```bash
# Connect to Supabase
psql "postgresql://postgres:password@db.xxx.supabase.co:5432/postgres"

# List tables
\dt

# Describe table
\d analysis

# Run SQL file
\i schema.sql
```

***

## Success Checklist

Your implementation is complete when:

* [ ] All dependencies installed
* [ ] TypeScript compiles without errors
* [ ] Database schema matches spec
* [ ] No `schema_version` in codebase
* [ ] Analysis vendor is required
* [ ] Analysis body is string type
* [ ] Party has uuid field
* [ ] All compliance tests pass
* [ ] MCP server starts successfully
* [ ] Tools are callable from AI assistant
* [ ] Can create, read, search vCons
* [ ] vCons are spec-compliant
* [ ] Database operations work correctly

***

**🎉 Congratulations!** You've built a fully spec-compliant IETF vCon MCP Server!

***

*Last Updated: October 7, 2025*\
*Spec Version: draft-ietf-vcon-vcon-core-02*\
*vCon Schema: 0.4.0*


# Plugin Development

## Overview

The vCon MCP Server supports a plugin architecture that allows you to extend its functionality with custom features. This guide explains how to create your own plugins.

## Plugin Interface

Plugins implement the `VConPlugin` interface which provides lifecycle hooks and tool registration capabilities.

### Basic Plugin Structure

```typescript
import { VConPlugin, RequestContext } from 'vcon-mcp/hooks';
import { VCon } from 'vcon-mcp/types';
import { Tool } from '@modelcontextprotocol/sdk/types';

export default class MyPlugin implements VConPlugin {
  name = 'my-plugin';
  version = '1.0.0';
  
  async initialize(config: any): Promise<void> {
    console.error('✅ My Plugin initialized');
  }
  
  async shutdown(): Promise<void> {
    console.error('👋 My Plugin shutting down');
  }
  
  // Implement hooks as needed...
}
```

## Available Hooks

### Lifecycle Hooks

#### `initialize(config)`

Called when the server starts up. Use this to set up connections, load configuration, etc.

```typescript
async initialize(config: any): Promise<void> {
  this.supabase = config.supabase;
  this.queries = config.queries;
}
```

#### `shutdown()`

Called when the server is shutting down. Clean up resources here.

```typescript
async shutdown(): Promise<void> {
  await this.database.disconnect();
}
```

### Data Operation Hooks

#### `beforeCreate(vcon, context)`

Called before a vCon is created. Can modify the vCon or throw to block creation.

```typescript
async beforeCreate(vcon: VCon, context: RequestContext): Promise<VCon> {
  // Add custom metadata
  vcon.extensions = vcon.extensions || [];
  vcon.extensions.push('my-plugin-v1');
  
  return vcon;
}
```

#### `afterCreate(vcon, context)`

Called after a vCon is successfully created.

```typescript
async afterCreate(vcon: VCon, context: RequestContext): Promise<void> {
  // Send notification, log to external system, etc.
  await this.notifyExternalSystem(vcon);
}
```

#### `beforeRead(uuid, context)`

Called before a vCon is read. Throw an error to block access.

```typescript
async beforeRead(uuid: string, context: RequestContext): Promise<void> {
  // Check access permissions
  if (!this.hasAccess(context.userId, uuid)) {
    throw new Error('Access denied');
  }
}
```

#### `afterRead(vcon, context)`

Called after a vCon is read. Can modify the returned data (e.g., redact sensitive information).

```typescript
async afterRead(vcon: VCon, context: RequestContext): Promise<VCon> {
  // Redact email addresses from parties
  vcon.parties = vcon.parties?.map(party => ({
    ...party,
    mailto: '[REDACTED]'
  }));
  
  return vcon;
}
```

#### `beforeUpdate(uuid, updates, context)`

Called before a vCon is updated.

```typescript
async beforeUpdate(uuid: string, updates: any, context: RequestContext): Promise<void> {
  // Validate updates meet business rules
  await this.validateBusinessRules(updates);
}
```

#### `afterUpdate(vcon, context)`

Called after a vCon is updated.

```typescript
async afterUpdate(vcon: VCon, context: RequestContext): Promise<void> {
  // Update cache, send webhooks, etc.
  await this.invalidateCache(vcon.uuid);
}
```

#### `beforeDelete(uuid, context)`

Called before a vCon is deleted. Throw to prevent deletion.

```typescript
async beforeDelete(uuid: string, context: RequestContext): Promise<void> {
  // Check if vCon has legal hold
  if (await this.hasLegalHold(uuid)) {
    throw new Error('Cannot delete: legal hold active');
  }
}
```

#### `afterDelete(uuid, context)`

Called after a vCon is deleted.

```typescript
async afterDelete(uuid: string, context: RequestContext): Promise<void> {
  // Clean up related resources
  await this.deleteRelatedFiles(uuid);
}
```

#### `beforeSearch(criteria, context)`

Called before searching vCons. Can modify search criteria.

```typescript
async beforeSearch(criteria: SearchCriteria, context: RequestContext): Promise<SearchCriteria> {
  // Add tenant filter based on user
  return {
    ...criteria,
    tenantId: context.userId
  };
}
```

#### `afterSearch(results, context)`

Called after searching vCons. Can filter or modify results.

```typescript
async afterSearch(results: VCon[], context: RequestContext): Promise<VCon[]> {
  // Filter out sensitive vCons
  return results.filter(vcon => !this.isSensitive(vcon));
}
```

### Tool Registration

#### `registerTools()`

Register additional MCP tools that will be exposed to clients.

```typescript
registerTools(): Tool[] {
  return [
    {
      name: 'my_custom_tool',
      description: 'Does something custom',
      inputSchema: {
        type: 'object',
        properties: {
          param: { type: 'string', description: 'A parameter' }
        },
        required: ['param']
      }
    }
  ];
}
```

**Note:** You'll need to handle the tool execution in your plugin by registering a tool handler separately.

#### `registerResources()`

Register additional MCP resources.

```typescript
registerResources(): Resource[] {
  return [
    {
      uri: 'myplugin://stats',
      name: 'Plugin Statistics',
      mimeType: 'application/json'
    }
  ];
}
```

## Request Context

All hooks receive a `RequestContext` object with information about the request:

```typescript
interface RequestContext {
  userId?: string;        // User making the request
  purpose?: string;       // Purpose of the operation
  ipAddress?: string;     // Client IP address
  timestamp: Date;        // When the request was made
  metadata?: Record<string, any>;  // Additional metadata
}
```

## Loading Plugins

### Via Environment Variable

Set the `VCON_PLUGINS_PATH` environment variable to load plugins:

```bash
# Single plugin
VCON_PLUGINS_PATH=./my-plugin.js

# Multiple plugins (comma-separated)
VCON_PLUGINS_PATH=@vcon/privacy-suite,./custom-plugin.js

# From npm package
VCON_PLUGINS_PATH=@mycompany/vcon-plugin
```

### Plugin Configuration

Plugins receive configuration from environment variables:

```bash
VCON_LICENSE_KEY=your-license-key
VCON_OFFLINE_MODE=false
```

Access these in your plugin constructor:

```typescript
constructor(config: any) {
  this.licenseKey = config.licenseKey;
  this.offlineMode = config.offlineMode;
  this.supabase = config.supabase;
}
```

## Example: Simple Logging Plugin

```typescript
import { VConPlugin, RequestContext } from 'vcon-mcp/hooks';
import { VCon } from 'vcon-mcp/types';

export default class LoggingPlugin implements VConPlugin {
  name = 'logging-plugin';
  version = '1.0.0';
  
  async initialize(config: any): Promise<void> {
    console.error('✅ Logging Plugin initialized');
  }
  
  async afterCreate(vcon: VCon, context: RequestContext): Promise<void> {
    console.error(`📝 vCon created: ${vcon.uuid} by user ${context.userId}`);
  }
  
  async afterRead(vcon: VCon, context: RequestContext): Promise<VCon> {
    console.error(`👀 vCon read: ${vcon.uuid} by user ${context.userId}`);
    return vcon;
  }
  
  async afterDelete(uuid: string, context: RequestContext): Promise<void> {
    console.error(`🗑️  vCon deleted: ${uuid} by user ${context.userId}`);
  }
}
```

## Example: Access Control Plugin

```typescript
import { VConPlugin, RequestContext } from 'vcon-mcp/hooks';
import { VCon } from 'vcon-mcp/types';

export default class AccessControlPlugin implements VConPlugin {
  name = 'access-control';
  version = '1.0.0';
  
  private permissions: Map<string, Set<string>> = new Map();
  
  async initialize(config: any): Promise<void> {
    // Load permissions from database
    await this.loadPermissions(config.supabase);
  }
  
  async beforeRead(uuid: string, context: RequestContext): Promise<void> {
    if (!context.userId) {
      throw new Error('Authentication required');
    }
    
    const userPermissions = this.permissions.get(context.userId);
    if (!userPermissions?.has(uuid)) {
      throw new Error(`Access denied to vCon ${uuid}`);
    }
  }
  
  async beforeDelete(uuid: string, context: RequestContext): Promise<void> {
    if (!context.userId) {
      throw new Error('Authentication required');
    }
    
    const userPermissions = this.permissions.get(context.userId);
    if (!userPermissions?.has(uuid)) {
      throw new Error(`Cannot delete vCon ${uuid}: access denied`);
    }
  }
  
  private async loadPermissions(supabase: any): Promise<void> {
    // Load from database
    const { data } = await supabase
      .from('permissions')
      .select('user_id, vcon_uuid');
    
    for (const perm of data || []) {
      if (!this.permissions.has(perm.user_id)) {
        this.permissions.set(perm.user_id, new Set());
      }
      this.permissions.get(perm.user_id)!.add(perm.vcon_uuid);
    }
  }
}
```

## Testing Your Plugin

Create a test file:

```typescript
import MyPlugin from './my-plugin';
import { VCon } from 'vcon-mcp/types';

const plugin = new MyPlugin({
  licenseKey: 'test-key',
  offlineMode: true
});

await plugin.initialize({});

const vcon: VCon = {
  vcon: '0.4.0',
  uuid: '123e4567-e89b-12d3-a456-426614174000',
  created_at: new Date().toISOString(),
  parties: []
};

const context = {
  timestamp: new Date(),
  userId: 'test-user'
};

const modified = await plugin.beforeCreate(vcon, context);
console.log('Modified vCon:', modified);
```

## Best Practices

1. **Error Handling**: Always catch and properly handle errors in hooks
2. **Performance**: Keep hook execution fast - avoid slow operations
3. **Logging**: Use `console.error()` for plugin logs (stdout is reserved for MCP protocol)
4. **Type Safety**: Use TypeScript and proper type annotations
5. **Documentation**: Document your plugin's configuration options and behavior
6. **Testing**: Write tests for your plugin hooks
7. **Versioning**: Use semantic versioning for your plugin

## Publishing Your Plugin

### As npm Package

1. Create `package.json`:

```json
{
  "name": "@mycompany/vcon-plugin",
  "version": "1.0.0",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "peerDependencies": {
    "vcon-mcp": "^1.0.0"
  }
}
```

2. Build and publish:

```bash
npm run build
npm publish
```

3. Users install with:

```bash
npm install @mycompany/vcon-plugin
```

### As Local Module

Users can load plugins from local files:

```bash
VCON_PLUGINS_PATH=./plugins/my-plugin.js
```

## Plugin Ideas

* **Audit Logging**: Log all operations to external system
* **Webhooks**: Send notifications on vCon events
* **Encryption**: Encrypt sensitive fields at rest
* **Multi-tenancy**: Enforce tenant isolation
* **Rate Limiting**: Limit operations per user
* **Caching**: Cache frequently accessed vCons
* **Analytics**: Collect usage statistics
* **Validation**: Enforce custom business rules
* **Integration**: Sync with external systems (CRM, etc.)

## Support

For questions or issues with plugin development:

* Create an issue on GitHub
* Join our community discussions
* Review the plugin interface source code

## License

When creating plugins, ensure they comply with the MIT license of the core server, or clearly state your plugin's license.


# Testing

## ✅ Quick Test Results

Your MCP server is **fully functional**! All 46 MCP tools and 35+ REST API endpoints are tested:

**MCP Tools (35):** CRUD (create, get, update, delete, add\_dialog, add\_analysis, add\_attachment, create\_from\_template), Search (search\_vcons, search\_vcons\_content, search\_vcons\_semantic, search\_vcons\_hybrid), Contract (vcon\_fetch, vcon\_search, vcon\_capabilities, vcon\_taxonomy, describe\_response\_shape), Tags (manage\_tag, get\_tags, remove\_all\_tags, search\_by\_tags, get\_unique\_tags), Schema (get\_schema, get\_examples), Database (get\_database\_shape, get\_database\_stats, analyze\_query, get\_database\_size\_info, get\_smart\_search\_limits), Analytics (get\_database\_analytics, get\_monthly\_growth\_analytics, get\_content\_analytics, get\_tag\_analytics, get\_attachment\_analytics, get\_database\_health\_metrics)

**REST API (30+ endpoints):** Full parity with MCP tools via HTTP/JSON at `/api/v1`

## 🔧 Three Ways to Test

### Option 1: MCP Inspector (Best for Development) 🎯

The MCP Inspector provides a GUI for testing your server.

**Start the Inspector:**

```bash
# Using npm script (recommended)
npm run test:console

# Or directly with npx
npx @modelcontextprotocol/inspector tsx src/index.ts
```

Then open **<http://localhost:5173>** in your browser.

**What you can do:**

* Browse available tools visually
* Test each tool with form inputs
* See real-time request/response logs
* Debug tool parameters and results

**Try these in the Inspector:**

1. **search\_vcons**

   ```json
   {
     "subject": "Chevrolet",
     "limit": 5
   }
   ```
2. **get\_vcon**

   ```json
   {
     "uuid": "01f344c1-02c2-478f-9441-f25bdc85bdaf"
   }
   ```

***

### Option 2: Claude Desktop (Best for Real Usage) 💬

Integrate your MCP server directly with Claude Desktop.

**Setup Steps:**

1. **Copy the config file:**

   ```bash
   cp /Users/thomashowe/Documents/GitHub/vcon-mcp/claude-desktop-config.json \
      ~/Library/Application\ Support/Claude/claude_desktop_config.json
   ```
2. **Restart Claude Desktop**
3. **Verify it loaded:**
   * Look for the 🔌 MCP icon in Claude Desktop
   * It should show "vcon" as an available server
   * You should see 46 tools available

**Test in Claude:**

Try asking Claude:

* "Search for vCons about Chevrolet vehicles"
* "Get the vCon with UUID 01f344c1-02c2-478f-9441-f25bdc85bdaf"
* "Show me conversations from today"
* "Create a new vCon for a customer support call"

**Example prompts:**

```
"Find all conversations mentioning Nissan from the last week"

"Get the full details of vCon 01f344c1-02c2-478f-9441-f25bdc85bdaf 
and summarize the conversation"

"Create a new vCon for a customer service call between an agent 
named Alice and a customer named Bob about a product inquiry"

"Add sentiment analysis to vCon 01f344c1-02c2-478f-9441-f25bdc85bdaf 
showing positive sentiment with score 0.85"
```

***

### Option 3: Direct Script Testing (Best for Automation) 🤖

Run the test script directly to verify all functionality.

**Run tests:**

```bash
cd /Users/thomashowe/Documents/GitHub/vcon-mcp
npx tsx scripts/test-mcp-tools.ts
```

### Unit test suite

Run the Vitest suite (includes search RPC method tests):

```bash
npm test
```

Relevant files:

* `tests/search.test.ts` – RPC wiring for keyword, semantic, hybrid search

**What it tests:**

1. ✅ Search vCons by subject
2. ✅ Retrieve full vCon with all relationships
3. ✅ Create new vCon with parties
4. ✅ Add dialog to vCon
5. ✅ Add AI analysis
6. ✅ Add attachments
7. ✅ Search by party
8. ✅ Delete vCon

**Output shows:**

* Each test step with results
* Actual data from your database
* Success/failure status
* Complete validation

***

## 📊 Sample Test Data

Your database has real production data:

### Example vCon UUIDs to test with:

```
01f344c1-02c2-478f-9441-f25bdc85bdaf  - Chevrolet Silverado inquiry
ac8b993d-f67d-4579-8d38-63e56b71234a  - Champion Chevrolet GMC
554f6095-8b89-40a6-9103-64d905b5b385  - Pride Chevrolet
002c489d-3eec-4596-bc72-da4eb3b05caa  - Burleson Nissan reservation
```

### Sample Queries:

**Search by subject:**

```json
{
  "subject": "Chevrolet",
  "limit": 10
}
```

**Search by party:**

```json
{
  "party_name": "Denis Duarte",
  "limit": 5
}
```

**Date range search:**

```json
{
  "start_date": "2025-08-01",
  "end_date": "2025-09-01",
  "limit": 20
}
```

***

## 🎯 Recommended Testing Flow

### 1. **Quick Validation** (2 minutes)

```bash
npx tsx scripts/test-mcp-tools.ts
```

✅ Confirms all tools work

### 2. **Interactive Testing** (10 minutes)

```bash
npm run test:console
```

* Open <http://localhost:5173>
* Test each tool manually
* Experiment with different parameters

### 3. **Real Usage** (ongoing)

* Set up Claude Desktop integration
* Use natural language to interact with vCons
* Build workflows with AI assistance

***

## 🔍 Debugging

### View Server Logs

```bash
# Find the dev server process
ps aux | grep "tsx watch"

# Server logs appear in the terminal where you ran `npm run dev`
```

### Database Queries

```bash
# Connect to database
psql postgresql://postgres:postgres@127.0.0.1:54322/postgres

# Useful queries
SELECT COUNT(*) FROM vcons;
SELECT uuid, subject FROM vcons LIMIT 5;
SELECT * FROM parties WHERE name ILIKE '%customer%';
```

### Check Supabase Status

```bash
supabase status
```

***

## 🚀 Advanced Testing

### Load Testing

Create a script to generate many vCons:

```bash
for i in {1..100}; do
  npx tsx -e "
    import { getSupabaseClient } from './src/db/client.js';
    import { VConQueries } from './src/db/queries.js';
    const supabase = getSupabaseClient();
    const queries = new VConQueries(supabase);
    await queries.createVCon({
      vcon: '0.4.0',
      uuid: crypto.randomUUID(),
      created_at: new Date().toISOString(),
      subject: 'Load Test vCon $i',
      parties: [{ name: 'Test User' }]
    });
  "
done
```

### Integration Testing

Test with external systems:

```typescript
// Example: Test with webhook
const result = await fetch('YOUR_WEBHOOK_URL', {
  method: 'POST',
  body: JSON.stringify({
    tool: 'search_vcons',
    params: { subject: 'test' }
  })
});
```

***

## 📝 Test Checklist

Before deploying:

* [ ] All 46 MCP tools tested via script
* [ ] REST API endpoints tested (`npm test` includes supertest coverage)
* [ ] MCP Inspector loads and shows tools
* [ ] Can search vCons by subject
* [ ] Can retrieve full vCon with relationships
* [ ] Can create new vCons
* [ ] Can add dialogs, analysis, attachments
* [ ] Can delete vCons
* [ ] Claude Desktop integration works (optional)
* [ ] Database queries return correct data
* [ ] Server restarts properly

***

## 🎉 You're Ready!

Your MCP server is fully tested and operational. Choose your preferred testing method:

* **Quick validation**: Run `npx tsx scripts/test-mcp-tools.ts`
* **Interactive testing**: Use MCP Inspector
* **Production usage**: Integrate with Claude Desktop

All 4,443 production vCons are loaded and accessible!


# Embeddings

> **⚠️ Historical reference document.** The SQL examples in Steps 1–2 below reflect an early 1536-dim / `text-embedding-ada-002` design. The current implementation uses **`text-embedding-3-small` at 384 dimensions**. For the authoritative setup, see [`docs/development/INGEST_AND_EMBEDDINGS.md`](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/INGEST_AND_EMBEDDINGS.md).

## Overview

This guide explains how to implement semantic search for vCon conversation content in Supabase PostgreSQL using the **pgvector** extension for vector similarity search.

***

## Architecture

### High-Level Flow

```
vCon Content → Embedding API → Vector (array of floats) → PostgreSQL (pgvector) → Similarity Search
```

### Components

1. **pgvector Extension** - PostgreSQL extension for vector similarity
2. **Embedding Service** - OpenAI, Sentence Transformers, or custom
3. **Vector Storage** - New columns in Supabase tables
4. **Similarity Functions** - Cosine similarity, L2 distance, inner product
5. **Indexes** - HNSW or IVFFlat indexes for fast retrieval

***

## Step 1: Enable pgvector Extension

### In Supabase Dashboard

```sql
-- Enable the pgvector extension
CREATE EXTENSION IF NOT EXISTS vector;
```

### Verify Installation

```sql
SELECT * FROM pg_extension WHERE extname = 'vector';
```

***

## Step 2: Add Vector Columns to Schema

### Add Embedding Columns

```sql
-- Add vector columns to existing tables
ALTER TABLE vcons 
ADD COLUMN subject_embedding vector(384),  -- text-embedding-3-small dimension
ADD COLUMN subject_embedding_model TEXT DEFAULT 'text-embedding-3-small',
ADD COLUMN subject_embedding_updated_at TIMESTAMPTZ;

ALTER TABLE dialog
ADD COLUMN content_embedding vector(384),
ADD COLUMN content_embedding_model TEXT DEFAULT 'text-embedding-3-small',
ADD COLUMN content_embedding_updated_at TIMESTAMPTZ;

ALTER TABLE analysis
ADD COLUMN summary_embedding vector(384),
ADD COLUMN summary_embedding_model TEXT DEFAULT 'text-embedding-3-small',
ADD COLUMN summary_embedding_updated_at TIMESTAMPTZ;
```

### Alternative: Dedicated Embeddings Table

For more flexibility, create a separate embeddings table:

```sql
-- Dedicated embeddings table for all content types
CREATE TABLE vcon_embeddings (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    
    -- What is being embedded
    content_type TEXT NOT NULL, -- 'subject', 'dialog', 'analysis_summary'
    content_reference TEXT, -- dialog_index, analysis_index, etc.
    content_text TEXT NOT NULL, -- Original text that was embedded
    
    -- The embedding
    embedding vector(384) NOT NULL,
    embedding_model TEXT NOT NULL DEFAULT 'text-embedding-3-small',
    embedding_dimension INTEGER NOT NULL DEFAULT 384,
    
    -- Metadata
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    
    -- Composite index for lookups
    CONSTRAINT vcon_embeddings_unique UNIQUE (vcon_id, content_type, content_reference)
);

-- Indexes for fast retrieval
CREATE INDEX idx_vcon_embeddings_vcon_id ON vcon_embeddings(vcon_id);
CREATE INDEX idx_vcon_embeddings_content_type ON vcon_embeddings(content_type);
```

***

## Step 3: Create Vector Indexes

### HNSW Index (Recommended for Most Cases)

```sql
-- HNSW index for approximate nearest neighbor search
-- Good for: General purpose, balanced performance
CREATE INDEX ON vcon_embeddings 
USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

-- For L2 distance
CREATE INDEX ON vcon_embeddings 
USING hnsw (embedding vector_l2_ops)
WITH (m = 16, ef_construction = 64);

-- For inner product
CREATE INDEX ON vcon_embeddings 
USING hnsw (embedding vector_ip_ops)
WITH (m = 16, ef_construction = 64);
```

**HNSW Parameters:**

* `m`: Max connections per layer (default: 16, higher = more accurate but slower)
* `ef_construction`: Size of dynamic candidate list (default: 64, higher = better recall)

### IVFFlat Index (For Large Datasets)

```sql
-- IVFFlat index for large-scale search
-- Good for: 1M+ vectors, when you can tolerate some accuracy loss
CREATE INDEX ON vcon_embeddings 
USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 100);

-- Adjust lists based on dataset size:
-- lists = rows / 1000 for small datasets (< 1M rows)
-- lists = sqrt(rows) for larger datasets
```

**When to Use Which Index:**

* **HNSW**: < 1M vectors, need high accuracy, have memory
* **IVFFlat**: > 1M vectors, can trade accuracy for speed
* **No Index**: < 10K vectors (brute force is fast enough)

***

## Step 4: Generate Embeddings

### Option A: Using OpenAI API

```python
import openai
from supabase import create_client

# Initialize clients
openai.api_key = "your-openai-key"
supabase = create_client("your-supabase-url", "your-supabase-key")

def generate_embedding(text: str, model: str = "text-embedding-3-small") -> list[float]:
    """Generate embedding using OpenAI API."""
    response = openai.embeddings.create(
        input=text,
        model=model
    )
    return response.data[0].embedding

def embed_vcon_content(vcon_id: str, subject: str, dialog_texts: list[str]):
    """Generate and store embeddings for vCon content."""
    
    # Embed subject
    if subject:
        subject_embedding = generate_embedding(subject)
        supabase.table('vcon_embeddings').upsert({
            'vcon_id': vcon_id,
            'content_type': 'subject',
            'content_reference': None,
            'content_text': subject,
            'embedding': subject_embedding,
            'embedding_model': 'text-embedding-3-small',
            'embedding_dimension': 384
        }).execute()
    
    # Embed dialogs
    for idx, text in enumerate(dialog_texts):
        if text and len(text.strip()) > 0:
            dialog_embedding = generate_embedding(text)
            supabase.table('vcon_embeddings').upsert({
                'vcon_id': vcon_id,
                'content_type': 'dialog',
                'content_reference': str(idx),
                'content_text': text,
                'embedding': dialog_embedding,
                'embedding_model': 'text-embedding-ada-002',
                'embedding_dimension': 1536
            }).execute()

# Usage
embed_vcon_content(
    vcon_id="123e4567-e89b-12d3-a456-426614174000",
    subject="Customer support call regarding billing issue",
    dialog_texts=[
        "Hello, I have a question about my bill",
        "I can help with that. What's your account number?",
        "It's 12345. I was charged twice this month."
    ]
)
```

### Option B: Using Sentence Transformers (Local/Self-Hosted)

```python
from sentence_transformers import SentenceTransformer
from supabase import create_client

# Load model (384-dim or 768-dim depending on model)
model = SentenceTransformer('all-MiniLM-L6-v2')  # 384 dimensions

supabase = create_client("your-supabase-url", "your-supabase-key")

def generate_embedding_local(text: str) -> list[float]:
    """Generate embedding using local Sentence Transformers model."""
    embedding = model.encode(text)
    return embedding.tolist()

# Update schema for 384-dim embeddings
# ALTER TABLE vcon_embeddings ALTER COLUMN embedding TYPE vector(384);
```

### Option C: Batch Processing with Edge Functions (Preferred in this repo)

```typescript
// Supabase Edge Function for batch embedding
import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'

serve(async (req) => {
  const { vcon_id, texts } = await req.json()
  
  // Call OpenAI API
  const embeddings = await Promise.all(
    texts.map(text => generateEmbedding(text))
  )
  
  // Store in Supabase
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL'),
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')
  )
  
  for (let i = 0; i < embeddings.length; i++) {
    await supabase.table('vcon_embeddings').insert({
      vcon_id,
      content_type: 'dialog',
      content_reference: String(i),
      content_text: texts[i],
      embedding: embeddings[i]
    })
  }
  
  return new Response(JSON.stringify({ success: true }), {
    headers: { 'Content-Type': 'application/json' }
  })
})
```

See [`docs/development/INGEST_AND_EMBEDDINGS.md`](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/INGEST_AND_EMBEDDINGS.md) for the production-ready function (`supabase/functions/embed-vcons/index.ts`), environment variables, and Cron scheduling. This repository standardizes on 384‑dim embeddings to match the migrations and HNSW index.

***

## Step 5: Semantic Search Queries

### Basic Cosine Similarity Search

```sql
-- Function to search by semantic similarity
CREATE OR REPLACE FUNCTION search_vcons_semantic(
    query_embedding vector(384),
    match_threshold float DEFAULT 0.7,
    match_count int DEFAULT 20
)
RETURNS TABLE (
    vcon_id uuid,
    content_type text,
    content_text text,
    similarity float
) AS $$
BEGIN
    RETURN QUERY
    SELECT
        e.vcon_id,
        e.content_type,
        e.content_text,
        1 - (e.embedding <=> query_embedding) AS similarity
    FROM vcon_embeddings e
    WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
    ORDER BY e.embedding <=> query_embedding
    LIMIT match_count;
END;
$$ LANGUAGE plpgsql;

-- Usage
SELECT * FROM search_vcons_semantic(
    (SELECT embedding FROM vcon_embeddings WHERE id = 'some-id'), -- query embedding
    0.7, -- minimum similarity
    20   -- max results
);
```

### Similarity Operators in pgvector

```sql
-- Cosine distance (most common for semantic search)
-- Returns 0-2, where 0 = identical, 1 = orthogonal, 2 = opposite
embedding1 <=> embedding2

-- L2 distance (Euclidean)
-- Returns >= 0, where 0 = identical
embedding1 <-> embedding2

-- Inner product (negative inner product)
-- Returns negative value, larger (less negative) = more similar
embedding1 <#> embedding2

-- Cosine similarity (1 - cosine distance)
-- Returns 0-1, where 1 = identical, 0 = orthogonal
1 - (embedding1 <=> embedding2)
```

### Python Implementation

```python
from supabase import create_client
import openai

class VConSemanticSearch:
    def __init__(self, supabase_url: str, supabase_key: str, openai_key: str):
        self.supabase = create_client(supabase_url, supabase_key)
        openai.api_key = openai_key
    
    def search(
        self, 
        query: str, 
        threshold: float = 0.7, 
        limit: int = 20,
        content_types: list[str] = None
    ) -> list[dict]:
        """
        Semantic search for vCons.
        
        Args:
            query: Natural language search query
            threshold: Minimum similarity (0-1)
            limit: Max results
            content_types: Filter by content type ['subject', 'dialog', 'analysis_summary']
        
        Returns:
            List of matching results with similarity scores
        """
        
        # Generate query embedding
        query_embedding = openai.embeddings.create(
            input=query,
            model="text-embedding-ada-002"
        ).data[0].embedding
        
        # Build query
        rpc_params = {
            'query_embedding': query_embedding,
            'match_threshold': threshold,
            'match_count': limit
        }
        
        # Execute search
        results = self.supabase.rpc(
            'search_vcons_semantic',
            rpc_params
        ).execute()
        
        # Group by vCon
        vcon_results = {}
        for row in results.data:
            vcon_id = row['vcon_id']
            if vcon_id not in vcon_results:
                vcon_results[vcon_id] = {
                    'vcon_id': vcon_id,
                    'max_similarity': row['similarity'],
                    'matches': []
                }
            
            vcon_results[vcon_id]['matches'].append({
                'content_type': row['content_type'],
                'content_text': row['content_text'],
                'similarity': row['similarity']
            })
        
        # Sort by max similarity
        return sorted(
            vcon_results.values(),
            key=lambda x: x['max_similarity'],
            reverse=True
        )

# Usage
searcher = VConSemanticSearch(
    supabase_url="your-url",
    supabase_key="your-key",
    openai_key="your-openai-key"
)

results = searcher.search(
    query="customer frustrated about billing errors",
    threshold=0.75,
    limit=10
)

for result in results:
    print(f"vCon {result['vcon_id']}: {result['max_similarity']:.3f}")
    for match in result['matches']:
        print(f"  - {match['content_type']}: {match['content_text'][:100]}...")
```

***

## Step 6: Hybrid Search (Semantic + Exact)

### SQL Function for Hybrid Search with Tags-from-Attachments

```sql
CREATE OR REPLACE FUNCTION search_vcons_hybrid(
    query_text text,
    query_embedding vector(1536),
    tag_filters jsonb DEFAULT '{}',
    semantic_weight float DEFAULT 0.5,
    match_threshold float DEFAULT 0.7,
    match_count int DEFAULT 20
)
RETURNS TABLE (
    vcon_id uuid,
    subject text,
    tags jsonb,
    semantic_score float,
    keyword_score float,
    combined_score float
) AS $$
BEGIN
    RETURN QUERY
    WITH tags_kv AS (
        SELECT a.vcon_id,
               split_part(elem, ':', 1) AS key,
               split_part(elem, ':', 2) AS value
        FROM attachments a
        CROSS JOIN LATERAL jsonb_array_elements_text(a.body::jsonb) AS elem
        WHERE a.type = 'tags' AND a.encoding = 'json'
    ),
    tags_agg AS (
        SELECT vcon_id, jsonb_object_agg(key, value) AS tags
        FROM tags_kv GROUP BY vcon_id
    ),
    semantic_results AS (
        SELECT
            e.vcon_id,
            MAX(1 - (e.embedding <=> query_embedding)) AS semantic_score
        FROM vcon_embeddings e
        WHERE 1 - (e.embedding <=> query_embedding) > match_threshold
        GROUP BY e.vcon_id
    ),
    keyword_results AS (
        SELECT
            v.id AS vcon_id,
            ts_rank_cd(
                setweight(to_tsvector('english', COALESCE(v.subject, '')), 'A') ||
                setweight(to_tsvector('english', COALESCE(d.body, '')), 'C') ||
                setweight(to_tsvector('english', COALESCE(a.body, '')), 'B'),
                plainto_tsquery('english', query_text)
            ) AS keyword_score
        FROM vcons v
        LEFT JOIN dialog d ON d.vcon_id = v.id
        LEFT JOIN analysis a ON a.vcon_id = v.id
        WHERE query_text IS NOT NULL
          AND (setweight(to_tsvector('english', COALESCE(v.subject, '')), 'A') ||
               setweight(to_tsvector('english', COALESCE(d.body, '')), 'C') ||
               setweight(to_tsvector('english', COALESCE(a.body, '')), 'B'))
              @@ plainto_tsquery('english', query_text)
    )
    SELECT
        v.id AS vcon_id,
        COALESCE(sr.semantic_score, 0) AS semantic_score,
        COALESCE(kr.keyword_score, 0) AS keyword_score,
        (COALESCE(sr.semantic_score, 0) * semantic_weight + 
         COALESCE(kr.keyword_score, 0) * (1 - semantic_weight)) AS combined_score
    FROM vcons v
    LEFT JOIN tags_agg ta ON ta.vcon_id = v.id
    LEFT JOIN semantic_results sr ON v.id = sr.vcon_id
    LEFT JOIN keyword_results kr ON v.id = kr.vcon_id
    WHERE (tag_filters = '{}'::jsonb OR (ta.tags IS NOT NULL AND ta.tags @> tag_filters))
      AND (sr.semantic_score IS NOT NULL OR kr.keyword_score IS NOT NULL)
    ORDER BY combined_score DESC
    LIMIT match_count;
END;
$$ LANGUAGE plpgsql;
```

### Python Implementation

```python
def hybrid_search(
    self,
    semantic_query: str = None,
    keyword_query: str = None,
    tags: dict = None,
    semantic_weight: float = 0.5,
    threshold: float = 0.7,
    limit: int = 20
) -> list[dict]:
    """
    Hybrid search combining semantic and keyword search with tag filters.
    
    Args:
        semantic_query: Natural language query for semantic search
        keyword_query: Keywords for full-text search
        tags: Exact tag filters
        semantic_weight: Weight for semantic vs keyword (0-1)
        threshold: Minimum semantic similarity
        limit: Max results
    """
    
    # Generate embedding if semantic query provided
    query_embedding = None
    if semantic_query:
        query_embedding = openai.embeddings.create(
            input=semantic_query,
            model="text-embedding-ada-002"
        ).data[0].embedding
    
    # Execute hybrid search
    results = self.supabase.rpc('search_vcons_hybrid', {
        'query_text': keyword_query or semantic_query or '',
        'query_embedding': query_embedding,
        'tag_filters': tags or {},
        'semantic_weight': semantic_weight,
        'match_threshold': threshold,
        'match_count': limit
    }).execute()
    
    return results.data

# Usage
results = searcher.hybrid_search(
    semantic_query="customer unhappy with billing",
    tags={"department": "support", "status": "open"},
    semantic_weight=0.7,
    limit=10
)
```

***

## Step 7: Automatic Embedding Generation

### Trigger for Automatic Embedding on Insert

```sql
-- Function to automatically generate embeddings
CREATE OR REPLACE FUNCTION generate_vcon_embeddings()
RETURNS TRIGGER AS $$
BEGIN
    -- Call Edge Function or external service to generate embeddings
    -- This is a placeholder - actual implementation would call embedding service
    
    PERFORM net.http_post(
        url := current_setting('app.embedding_service_url'),
        body := jsonb_build_object(
            'vcon_id', NEW.id,
            'subject', NEW.subject,
            'metadata', NEW.metadata
        )
    );
    
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

-- Trigger to automatically generate embeddings
CREATE TRIGGER trigger_generate_embeddings
    AFTER INSERT OR UPDATE OF subject, metadata ON vcons
    FOR EACH ROW
    EXECUTE FUNCTION generate_vcon_embeddings();
```

### Background Job for Batch Embedding

```python
import asyncio
from datetime import datetime, timedelta

async def embedding_worker():
    """Background worker to generate embeddings for new vCons."""
    
    while True:
        # Find vCons without embeddings
        result = supabase.table('vcons').select('id, subject').is_('subject_embedding', 'null').limit(100).execute()
        
        for vcon in result.data:
            try:
                # Generate embedding
                embedding = generate_embedding(vcon['subject'])
                
                # Update vCon
                supabase.table('vcons').update({
                    'subject_embedding': embedding,
                    'subject_embedding_updated_at': datetime.now().isoformat()
                }).eq('id', vcon['id']).execute()
                
            except Exception as e:
                print(f"Error embedding vCon {vcon['id']}: {e}")
        
        # Wait before next batch
        await asyncio.sleep(60)

# Run worker
asyncio.run(embedding_worker())
```

***

## Step 8: Performance Optimization

### Query Optimization

```sql
-- Set search parameters for better performance
SET hnsw.ef_search = 40; -- Default is 40, increase for better recall

-- For IVFFlat
SET ivfflat.probes = 10; -- Default is 1, increase for better recall
```

### Embedding Dimension Reduction

```python
# Use smaller embedding models for better performance
# OpenAI text-embedding-3-small: 1536 dims (default) or can be reduced
# Sentence Transformers all-MiniLM-L6-v2: 384 dims

# Reduce OpenAI embedding dimensions
response = openai.embeddings.create(
    input=text,
    model="text-embedding-3-small",
    dimensions=512  # Reduce from 1536 to 512
)
```

### Caching Strategy

```python
import hashlib
import redis

redis_client = redis.Redis(host='localhost', port=6379, db=0)

def get_cached_embedding(text: str) -> list[float] | None:
    """Get embedding from cache."""
    cache_key = f"emb:{hashlib.md5(text.encode()).hexdigest()}"
    cached = redis_client.get(cache_key)
    if cached:
        return json.loads(cached)
    return None

def cache_embedding(text: str, embedding: list[float]):
    """Cache embedding for 7 days."""
    cache_key = f"emb:{hashlib.md5(text.encode()).hexdigest()}"
    redis_client.setex(cache_key, 604800, json.dumps(embedding))  # 7 days

def generate_embedding_with_cache(text: str) -> list[float]:
    """Generate embedding with caching."""
    cached = get_cached_embedding(text)
    if cached:
        return cached
    
    embedding = generate_embedding(text)
    cache_embedding(text, embedding)
    return embedding
```

***

## Step 9: Monitoring & Maintenance

### Track Embedding Coverage

```sql
-- Check embedding coverage
SELECT 
    COUNT(*) AS total_vcons,
    COUNT(subject_embedding) AS vcons_with_subject_embedding,
    COUNT(subject_embedding)::float / COUNT(*) * 100 AS coverage_percentage
FROM vcons;

-- Find vCons missing embeddings
SELECT id, subject, created_at
FROM vcons
WHERE subject_embedding IS NULL
ORDER BY created_at DESC
LIMIT 100;
```

### Monitor Search Performance

```sql
-- Enable timing
\timing on

-- Test query performance
EXPLAIN ANALYZE
SELECT *
FROM search_vcons_semantic(
    (SELECT embedding FROM vcon_embeddings WHERE id = 'test-id'),
    0.7,
    20
);
```

### Index Maintenance

```sql
-- Rebuild index if needed
REINDEX INDEX vcon_embeddings_embedding_idx;

-- Vacuum to reclaim space
VACUUM ANALYZE vcon_embeddings;
```

***

## Cost Considerations

### OpenAI Embedding Costs

* **text-embedding-ada-002**: $0.0001 per 1K tokens (\~750 words)
* **text-embedding-3-small**: $0.00002 per 1K tokens
* **text-embedding-3-large**: $0.00013 per 1K tokens

**Example Costs:**

* 100K vCons with 200-word subjects: $26.67 (ada-002)
* 1M dialog messages averaging 50 words: $66.67 (ada-002)

### Self-Hosted Alternative

Use Sentence Transformers locally:

* No API costs
* Faster for batch processing
* 384-768 dimensions (vs 1536)
* Slightly lower accuracy

***

## Summary

### Key Decisions

1. **Embedding Model**
   * OpenAI ada-002: Best accuracy, API costs
   * Sentence Transformers: Free, good accuracy, self-hosted
2. **Storage Strategy**
   * Dedicated embeddings table (recommended)
   * Embedded in existing tables (simpler)
3. **Index Type**
   * HNSW: < 1M vectors, high accuracy
   * IVFFlat: > 1M vectors, faster but less accurate
4. **Search Strategy**
   * Pure semantic: Best for natural language queries
   * Hybrid: Combine with tags and keywords for precision

### Implementation Checklist

* [ ] Enable pgvector extension
* [ ] Add vector columns to schema
* [ ] Create appropriate indexes
* [ ] Implement embedding generation
* [ ] Create search functions
* [ ] Set up caching
* [ ] Monitor performance
* [ ] Plan for maintenance

This architecture provides production-ready semantic search for vCon conversations in Supabase! 🚀


# Contributing

Thank you for your interest in contributing to the vCon MCP Server! This guide will help you get started.

## Table of Contents

* [Code of Conduct](#code-of-conduct)
* [Getting Started](#getting-started)
* [Development Workflow](#development-workflow)
* [Pull Request Process](#pull-request-process)
* [Coding Standards](#coding-standards)
* [Testing Requirements](#testing-requirements)
* [Documentation](#documentation)
* [Release Process](#release-process)

***

## Code of Conduct

### Our Pledge

We pledge to make participation in our project a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity, experience level, nationality, personal appearance, race, religion, or sexual identity.

### Our Standards

**Positive behavior includes:**

* Using welcoming and inclusive language
* Being respectful of differing viewpoints
* Accepting constructive criticism gracefully
* Focusing on what's best for the community
* Showing empathy towards others

**Unacceptable behavior includes:**

* Harassment, trolling, or derogatory comments
* Publishing others' private information
* Personal or political attacks
* Other unprofessional conduct

### Enforcement

Report violations to \[project maintainers]. All complaints will be reviewed and investigated promptly and fairly.

***

## Getting Started

### Prerequisites

Before contributing, ensure you have:

* **Node.js 18+** installed
* **Git** installed and configured
* **Supabase account** for database testing
* **GitHub account**
* Read the [Architecture documentation](/development/architecture)

### Initial Setup

1. **Fork the repository**

   ```bash
   # On GitHub, click "Fork" button
   ```
2. **Clone your fork**

   ```bash
   git clone https://github.com/YOUR_USERNAME/vcon-mcp.git
   cd vcon-mcp
   ```
3. **Add upstream remote**

   ```bash
   git remote add upstream https://github.com/vcon-dev/vcon-mcp.git
   ```
4. **Install dependencies**

   ```bash
   npm install
   ```
5. **Set up environment**

   ```bash
   cp .env.example .env
   # Edit .env with your Supabase credentials
   ```
6. **Run tests**

   ```bash
   npm test
   ```
7. **Build the project**

   ```bash
   npm run build
   ```

### Development Environment

We recommend:

* **VS Code** with these extensions:
  * ESLint
  * Prettier
  * TypeScript and JavaScript Language Features
  * GitLens
* **Database GUI**: Supabase Dashboard or pgAdmin

***

## Development Workflow

### Creating a Feature Branch

```bash
# Update your main branch
git checkout main
git pull upstream main

# Create feature branch
git checkout -b feature/your-feature-name

# Or for bug fixes
git checkout -b fix/issue-number-description
```

**Branch Naming Convention:**

* `feature/` - New features
* `fix/` - Bug fixes
* `docs/` - Documentation changes
* `refactor/` - Code refactoring
* `test/` - Test additions/changes
* `chore/` - Maintenance tasks

### Making Changes

1. **Make your changes**
   * Follow [Coding Standards](#coding-standards)
   * Add tests for new functionality
   * Update documentation
2. **Test your changes**

   ```bash
   # Run all tests
   npm test

   # Run specific test
   npm test -- search.test.ts

   # Run with coverage
   npm run test:coverage
   ```
3. **Lint and format**

   ```bash
   # Check linting
   npm run lint

   # Fix linting issues
   npm run lint:fix

   # Format code
   npm run format
   ```
4. **Build and verify**

   ```bash
   npm run build
   npm run dev  # Test locally
   ```

### Committing Changes

We use [Conventional Commits](https://www.conventionalcommits.org/):

```bash
git add .
git commit -m "type(scope): description"
```

**Commit Types:**

* `feat`: New feature
* `fix`: Bug fix
* `docs`: Documentation changes
* `style`: Code style changes (formatting)
* `refactor`: Code refactoring
* `test`: Test additions/changes
* `chore`: Maintenance tasks
* `perf`: Performance improvements

**Examples:**

```bash
git commit -m "feat(search): add hybrid search capability"
git commit -m "fix(validation): correct analysis vendor requirement"
git commit -m "docs(api): update tools reference"
git commit -m "test(crud): add tests for delete operation"
```

### Keeping Your Branch Updated

```bash
# Fetch upstream changes
git fetch upstream

# Rebase on upstream main
git rebase upstream/main

# Or merge if preferred
git merge upstream/main

# Force push if you rebased (after confirming with team)
git push origin feature/your-feature-name --force-with-lease
```

***

## Pull Request Process

### Before Submitting

Ensure your PR:

* [ ] Follows coding standards
* [ ] Includes tests for new functionality
* [ ] Passes all existing tests
* [ ] Updates relevant documentation
* [ ] Has no linting errors
* [ ] Builds successfully
* [ ] Has descriptive commit messages

### Creating a Pull Request

1. **Push your branch**

   ```bash
   git push origin feature/your-feature-name
   ```
2. **Open PR on GitHub**
   * Go to the repository
   * Click "New Pull Request"
   * Select your branch
   * Fill in the PR template

### PR Template

```markdown
## Description
Brief description of changes

## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update

## Testing
- [ ] Existing tests pass
- [ ] New tests added
- [ ] Manual testing completed

## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex code
- [ ] Documentation updated
- [ ] No new warnings generated

## Related Issues
Closes #123
```

### Review Process

1. **Automated Checks**
   * CI/CD runs tests
   * Linting checks
   * Build verification
2. **Code Review**
   * At least one maintainer approval required
   * Address all comments
   * Make requested changes
3. **Final Checks**
   * All conversations resolved
   * CI passes
   * Up to date with main
4. **Merge**
   * Maintainer will merge your PR
   * Branch will be deleted

### After Merge

1. **Update your local repo**

   ```bash
   git checkout main
   git pull upstream main
   ```
2. **Delete feature branch**

   ```bash
   git branch -d feature/your-feature-name
   git push origin --delete feature/your-feature-name
   ```

***

## Coding Standards

See [Code Style Guide](/development/code-style) for detailed standards.

### Quick Reference

**TypeScript:**

```typescript
// ✅ Good
export interface VCon {
  vcon: string;
  uuid: string;
  parties: Party[];
}

// ❌ Bad
export interface VCon {
  vcon: string;
  uuid: string;
  parties: any;  // Don't use 'any'
}
```

**Function Documentation:**

```typescript
/**
 * Create a new vCon in the database.
 * 
 * @param vcon - The vCon object to create
 * @returns Promise resolving to UUID of created vCon
 * @throws {ValidationError} If vCon fails validation
 * @throws {DatabaseError} If database operation fails
 */
async function createVCon(vcon: VCon): Promise<string> {
  // Implementation
}
```

**Error Handling:**

```typescript
// ✅ Good
try {
  const result = await queries.createVCon(vcon);
  return { success: true, uuid: result.uuid };
} catch (error) {
  logger.error('Failed to create vCon', { error, vcon });
  return {
    success: false,
    error: error instanceof Error ? error.message : 'Unknown error'
  };
}
```

***

## Testing Requirements

### Test Coverage

All contributions must maintain test coverage:

* **Minimum:** 80% overall coverage
* **New code:** 90% coverage required
* **Critical paths:** 100% coverage

### Writing Tests

```typescript
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { VConQueries } from '../src/db/queries';
import { createTestVCon } from './fixtures';

describe('VConQueries', () => {
  let queries: VConQueries;
  
  beforeAll(async () => {
    // Setup
    queries = new VConQueries(supabase);
  });
  
  afterAll(async () => {
    // Cleanup
  });
  
  it('should create a vCon', async () => {
    const vcon = createTestVCon();
    const result = await queries.createVCon(vcon);
    
    expect(result.uuid).toBeDefined();
    expect(result.uuid).toMatch(/^[0-9a-f-]{36}$/);
  });
  
  it('should reject invalid vCon', async () => {
    const invalidVCon = { vcon: '0.4.0' }; // Missing required fields
    
    await expect(queries.createVCon(invalidVCon as any))
      .rejects
      .toThrow('Validation failed');
  });
});
```

### Test Types

1. **Unit Tests** - Test individual functions
2. **Integration Tests** - Test component interactions
3. **Compliance Tests** - Test IETF spec compliance
4. **E2E Tests** - Test full workflows

### Running Tests

```bash
# All tests
npm test

# Watch mode
npm test -- --watch

# Specific file
npm test -- crud.test.ts

# Coverage report
npm run test:coverage

# Compliance tests only
npm run test:compliance
```

***

## Documentation

### Documentation Requirements

All contributions must include:

1. **Code Comments**
   * JSDoc for public APIs
   * Inline comments for complex logic
   * TODO/FIXME with issue numbers
2. **API Documentation**
   * Update `docs/api/` if changing tools/resources
   * Include examples
   * Document parameters and return values
3. **User Documentation**
   * Update `docs/guide/` if affecting user features
   * Add examples and use cases
   * Include troubleshooting tips
4. **README Updates**
   * Update if changing setup process
   * Keep examples current
   * Update feature list

### Documentation Style

See [Documentation Standards](/development/documentation) for details.

**Example:**

````typescript
/**
 * Search vCons using semantic similarity.
 * 
 * Uses AI embeddings to find conversations with similar meaning,
 * not just matching keywords.
 * 
 * @example
 * ```typescript
 * const results = await searchVConsSemantic(
 *   "frustrated customers",
 *   { threshold: 0.75, limit: 20 }
 * );
 * ```
 * 
 * @param query - Natural language search query
 * @param options - Search options
 * @param options.threshold - Minimum similarity (0-1), default 0.7
 * @param options.limit - Maximum results, default 20
 * @returns Promise resolving to search results
 * @throws {EmbeddingError} If embedding generation fails
 */
async function searchVConsSemantic(
  query: string,
  options?: SemanticSearchOptions
): Promise<SemanticResult[]> {
  // Implementation
}
````

***

## Release Process

### Versioning

We follow [Semantic Versioning](https://semver.org/):

* **Major (X.0.0)** - Breaking changes
* **Minor (0.X.0)** - New features (backward compatible)
* **Patch (0.0.X)** - Bug fixes

### Release Checklist

For maintainers:

1. **Update Version**

   ```bash
   npm version major|minor|patch
   ```
2. **Update CHANGELOG**
   * Document all changes
   * Group by type (Added, Changed, Fixed, Removed)
   * Include issue/PR numbers
3. **Create Release Branch**

   ```bash
   git checkout -b release/v1.2.0
   ```
4. **Final Testing**
   * Run full test suite
   * Test in production-like environment
   * Verify documentation
5. **Create Release PR**
   * Review all changes
   * Get approval from maintainers
6. **Merge, then tag**

   ```bash
   git checkout main && git pull
   git tag -a v1.2.0 -m "Release v1.2.0"
   git push origin v1.2.0
   ```

   Pushing the tag is the release. `.github/workflows/publish.yml` triggers on `v*` tags, builds, and publishes to npm with provenance. Do **not** run `npm publish` by hand — that is how `v1.4.0` ended up tagged but never published, and how `v1.5.0` ended up published with no tag.
7. **Confirm**

   ```bash
   npm view vcon-mcp version
   ```

   CI refuses to publish if the tag and `package.json` disagree, and a separate job fails any PR where `package.json` and the newest CHANGELOG heading drift apart.

***

## Getting Help

### Where to Ask

* **GitHub Issues** - Bug reports, feature requests
* **GitHub Discussions** - Questions, ideas, general discussion
* **Discord** - Real-time chat with community
* **Email** - Private matters to \[maintainers email]

### Issue Templates

**Bug Report:**

```markdown
**Describe the bug**
Clear description of the bug

**To Reproduce**
Steps to reproduce

**Expected behavior**
What should happen

**Actual behavior**
What actually happens

**Environment**
- OS: [e.g., macOS 13.0]
- Node.js: [e.g., 18.12.0]
- vCon MCP Server: [e.g., 1.0.0]
```

**Feature Request:**

```markdown
**Problem Statement**
What problem does this solve?

**Proposed Solution**
How would you solve it?

**Alternatives Considered**
Other approaches you considered

**Additional Context**
Any other relevant information
```

***

## Recognition

Contributors are recognized in:

* **CONTRIBUTORS.md** - All contributors listed
* **Release Notes** - Major contributions highlighted
* **GitHub Profile** - Contribution graph

We appreciate all contributions, big and small!

***

## License

By contributing, you agree that your contributions will be licensed under the MIT License.

***

## Questions?

If you have questions about contributing:

1. Check existing documentation
2. Search existing issues/discussions
3. Ask in GitHub Discussions
4. Contact maintainers

Thank you for contributing to vCon MCP Server! 🎉


# Code Style

This guide defines coding standards and best practices for the vCon MCP Server project.

## Table of Contents

* [TypeScript Style](#typescript-style)
* [Naming Conventions](#naming-conventions)
* [File Organization](#file-organization)
* [Comments and Documentation](#comments-and-documentation)
* [Error Handling](#error-handling)
* [Testing Style](#testing-style)
* [Git Practices](#git-practices)

***

## TypeScript Style

### General Principles

1. **Type Safety First** - No `any` types except where absolutely necessary
2. **Explicit Over Implicit** - Be clear about types and intentions
3. **Functional When Possible** - Prefer pure functions
4. **DRY Principle** - Don't Repeat Yourself

### Type Annotations

```typescript
// ✅ Good - Explicit types
function createVCon(vcon: VCon): Promise<{ uuid: string }> {
  return queries.createVCon(vcon);
}

// ❌ Bad - Missing types
function createVCon(vcon) {
  return queries.createVCon(vcon);
}

// ✅ Good - Return type explicit
async function getVCon(uuid: string): Promise<VCon> {
  const result = await queries.getVCon(uuid);
  return result;
}

// ⚠️ Acceptable - Return type can be inferred but explicit is better
async function getVCon(uuid: string) {
  return queries.getVCon(uuid);
}
```

### Interfaces vs Types

Use `interface` for object shapes that may be extended:

```typescript
// ✅ Good - Interface for extensible types
export interface VCon {
  vcon: string;
  uuid: string;
  parties: Party[];
}

export interface ExtendedVCon extends VCon {
  customField: string;
}
```

Use `type` for unions, intersections, and non-object types:

```typescript
// ✅ Good - Type for unions
export type DialogType = 'recording' | 'text' | 'transfer' | 'incomplete';

export type Encoding = 'none' | 'base64url' | 'json';

// ✅ Good - Type for intersection
export type VConWithMetadata = VCon & {
  metadata: Record<string, unknown>;
};
```

### Optional Properties

```typescript
// ✅ Good - Optional with ?
interface Analysis {
  type: string;
  vendor: string;
  product?: string;  // Optional
  schema?: string;   // Optional
}

// ❌ Bad - Using undefined
interface Analysis {
  type: string;
  vendor: string;
  product: string | undefined;
}
```

### Enums vs Union Types

Prefer union types over enums:

```typescript
// ✅ Good - Union type
export type DialogType = 'recording' | 'text' | 'transfer' | 'incomplete';

// ❌ Avoid - Enum (generates runtime code)
enum DialogType {
  Recording = 'recording',
  Text = 'text',
  Transfer = 'transfer',
  Incomplete = 'incomplete'
}
```

### Async/Await

Always use `async/await` over promises:

```typescript
// ✅ Good
async function createVCon(vcon: VCon): Promise<string> {
  const result = await queries.createVCon(vcon);
  return result.uuid;
}

// ❌ Bad
function createVCon(vcon: VCon): Promise<string> {
  return queries.createVCon(vcon).then(result => result.uuid);
}
```

### Arrow Functions

Use arrow functions for callbacks and short functions:

```typescript
// ✅ Good
const uuids = vcons.map(v => v.uuid);

const filtered = vcons.filter(v => v.subject?.includes('support'));

// ✅ Good - Multi-line
const processed = vcons.map(v => {
  const uuid = v.uuid;
  const subject = v.subject || 'Untitled';
  return { uuid, subject };
});
```

Use regular functions for methods and top-level functions:

```typescript
// ✅ Good
export function validateVCon(vcon: VCon): ValidationResult {
  // Implementation
}

// ✅ Good - Class method
class VConQueries {
  async createVCon(vcon: VCon): Promise<{ uuid: string }> {
    // Implementation
  }
}
```

### Destructuring

Use destructuring when accessing multiple properties:

```typescript
// ✅ Good
const { uuid, subject, parties } = vcon;

// ✅ Good - Function parameters
function displayVCon({ uuid, subject }: VCon): string {
  return `${subject} (${uuid})`;
}

// ⚠️ Acceptable for single property
const uuid = vcon.uuid;
```

### Template Literals

Use template literals over string concatenation:

```typescript
// ✅ Good
const message = `vCon ${uuid} created successfully`;

// ❌ Bad
const message = 'vCon ' + uuid + ' created successfully';
```

***

## Naming Conventions

### General Rules

* Use **camelCase** for variables, functions, and properties
* Use **PascalCase** for classes, interfaces, and types
* Use **UPPER\_SNAKE\_CASE** for constants
* Use **kebab-case** for file names

### Files

```
✅ Good file names:
vcon-queries.ts
search-tools.ts
validation-utils.ts
types/vcon.ts

❌ Bad file names:
VConQueries.ts
searchTools.ts
Validation_Utils.ts
```

### Variables and Functions

```typescript
// ✅ Good
const vconUuid = '123e4567-e89b-12d3-a456-426614174000';
const maxResults = 100;
let isValid = false;

function createVCon(vcon: VCon): Promise<string> {}
function validateVConStructure(vcon: VCon): boolean {}

// ❌ Bad
const VConUUID = '...';  // Use camelCase
const max_results = 100; // Use camelCase
let is_valid = false;    // Use camelCase

function CreateVCon() {}           // Use camelCase
function validate_vcon_structure() {} // Use camelCase
```

### Classes and Interfaces

```typescript
// ✅ Good
class VConQueries {}
interface VCon {}
interface SearchOptions {}
type DialogType = ...;

// ❌ Bad
class vconQueries {}   // Use PascalCase
interface vCon {}      // Use PascalCase
type dialogType = ...; // Use PascalCase
```

### Constants

```typescript
// ✅ Good
const VCON_VERSION = '0.4.0';
const MAX_SEARCH_RESULTS = 1000;
const DEFAULT_THRESHOLD = 0.7;

// ❌ Bad
const vconVersion = '0.3.0'; // Use UPPER_SNAKE_CASE for constants
const MaxSearchResults = 1000;
```

### Boolean Variables

Prefix with `is`, `has`, `should`, or `can`:

```typescript
// ✅ Good
const isValid = true;
const hasParties = vcon.parties.length > 0;
const shouldValidate = options.validate ?? true;
const canDelete = user.permissions.includes('delete');

// ❌ Bad
const valid = true;      // Not clear it's boolean
const parties = true;    // Confusing name
const validate = true;   // Could be a function
```

### Function Names

Use verbs for function names:

```typescript
// ✅ Good
function createVCon() {}
function getVCon() {}
function validateVCon() {}
function calculateScore() {}
function fetchResults() {}

// ❌ Bad
function vcon() {}      // Not descriptive
function vconCreation() {} // Noun, use createVCon
function validation() {}   // Noun, use validate
```

***

## File Organization

### Project Structure

```
src/
├── index.ts              # Entry point
├── types/               # Type definitions
│   ├── vcon.ts
│   ├── mcp.ts
│   └── index.ts
├── db/                  # Database layer
│   ├── client.ts
│   ├── queries.ts
│   └── index.ts
├── tools/               # MCP tools
│   ├── vcon-crud.ts
│   ├── search-tools.ts
│   ├── tag-tools.ts
│   └── index.ts
├── resources/           # MCP resources
│   └── index.ts
├── prompts/             # MCP prompts
│   └── index.ts
├── utils/               # Utilities
│   ├── validation.ts
│   ├── logger.ts
│   └── index.ts
└── hooks/               # Plugin system
    └── index.ts
```

### File Structure

Each file should follow this order:

```typescript
// 1. Imports - External first, then internal
import { createClient } from '@supabase/supabase-js';
import { z } from 'zod';

import { VCon, Analysis } from '../types/vcon.js';
import { validateVCon } from '../utils/validation.js';

// 2. Constants
const MAX_RETRIES = 3;
const RETRY_DELAY = 1000;

// 3. Type definitions
interface QueryOptions {
  limit?: number;
  offset?: number;
}

// 4. Main implementation
export class VConQueries {
  // Class implementation
}

// 5. Helper functions
function retry<T>(fn: () => Promise<T>, retries: number): Promise<T> {
  // Implementation
}

// 6. Exports
export { QueryOptions };
```

### Imports

```typescript
// ✅ Good - Organized by category
// External dependencies
import { createClient } from '@supabase/supabase-js';
import { z } from 'zod';

// Internal types
import type { VCon, Party } from '../types/vcon.js';

// Internal modules
import { getSupabaseClient } from './client.js';
import { validateVCon } from '../utils/validation.js';

// ❌ Bad - Disorganized
import { validateVCon } from '../utils/validation.js';
import { createClient } from '@supabase/supabase-js';
import { VCon } from '../types/vcon.js';
import { z } from 'zod';
```

### Exports

```typescript
// ✅ Good - Named exports
export function createVCon(vcon: VCon): Promise<string> {}
export function getVCon(uuid: string): Promise<VCon> {}

// ✅ Good - Export types
export type { VCon, Party, Dialog };

// ✅ Good - Re-exports in index.ts
export { createVCon, getVCon } from './queries.js';

// ❌ Avoid - Default exports (harder to refactor)
export default function createVCon() {}
```

***

## Comments and Documentation

### JSDoc Comments

All public APIs must have JSDoc comments:

````typescript
/**
 * Create a new vCon in the database.
 * 
 * Validates the vCon structure before insertion and returns the generated UUID.
 * All parties are inserted in a single transaction.
 * 
 * @param vcon - The vCon object to create
 * @returns Promise resolving to the UUID of the created vCon
 * @throws {ValidationError} If vCon fails validation
 * @throws {DatabaseError} If database operation fails
 * 
 * @example
 * ```typescript
 * const vcon: VCon = {
 *   vcon: '0.4.0',
 *   uuid: crypto.randomUUID(),
 *   created_at: new Date().toISOString(),
 *   parties: [{ name: 'Alice' }]
 * };
 * const uuid = await createVCon(vcon);
 * ```
 */
export async function createVCon(vcon: VCon): Promise<string> {
  // Implementation
}
````

### Inline Comments

Use sparingly for complex logic:

```typescript
// ✅ Good - Explains why, not what
function calculateRelevance(scores: number[]): number {
  // Normalize scores to 0-1 range before averaging
  // This prevents very high scores from skewing results
  const normalized = scores.map(s => Math.min(s, 1));
  return normalized.reduce((a, b) => a + b, 0) / normalized.length;
}

// ❌ Bad - States the obvious
function sum(a: number, b: number): number {
  // Add a and b together
  return a + b;
}
```

### TODO Comments

Always include context and assignee:

```typescript
// ✅ Good
// TODO(@username): Implement pagination for large result sets
// See issue #123 for requirements

// ❌ Bad
// TODO: fix this
```

### Section Comments

Use for major sections:

```typescript
// ============================================================================
// CRUD Operations
// ============================================================================

export async function createVCon(vcon: VCon): Promise<string> {}
export async function getVCon(uuid: string): Promise<VCon> {}
export async function updateVCon(uuid: string, updates: any): Promise<void> {}
export async function deleteVCon(uuid: string): Promise<void> {}

// ============================================================================
// Search Operations
// ============================================================================

export async function searchVCons(criteria: SearchCriteria): Promise<VCon[]> {}
```

***

## Error Handling

### Try-Catch Blocks

```typescript
// ✅ Good - Specific error handling
async function createVCon(vcon: VCon): Promise<Result> {
  try {
    const validation = validateVCon(vcon);
    if (!validation.valid) {
      return {
        success: false,
        error: `Validation failed: ${validation.errors.join(', ')}`
      };
    }
    
    const result = await queries.createVCon(vcon);
    return { success: true, uuid: result.uuid };
    
  } catch (error) {
    logger.error('Failed to create vCon', { error, vcon });
    
    if (error instanceof DatabaseError) {
      return { success: false, error: 'Database operation failed' };
    }
    
    return {
      success: false,
      error: error instanceof Error ? error.message : 'Unknown error'
    };
  }
}

// ❌ Bad - Swallowing errors
async function createVCon(vcon: VCon) {
  try {
    return await queries.createVCon(vcon);
  } catch (error) {
    console.log('Error');  // Too generic
    return null;           // Loses error information
  }
}
```

### Custom Errors

```typescript
// ✅ Good - Custom error classes
export class ValidationError extends Error {
  constructor(
    message: string,
    public readonly errors: string[]
  ) {
    super(message);
    this.name = 'ValidationError';
  }
}

export class DatabaseError extends Error {
  constructor(
    message: string,
    public readonly cause?: Error
  ) {
    super(message);
    this.name = 'DatabaseError';
  }
}

// Usage
if (!validation.valid) {
  throw new ValidationError(
    'vCon validation failed',
    validation.errors
  );
}
```

***

## Testing Style

### Test Structure

```typescript
import { describe, it, expect, beforeAll, afterAll, beforeEach } from 'vitest';

describe('VConQueries', () => {
  let queries: VConQueries;
  let testVConUuid: string;
  
  beforeAll(async () => {
    // One-time setup
    queries = new VConQueries(supabase);
  });
  
  afterAll(async () => {
    // One-time cleanup
    if (testVConUuid) {
      await queries.deleteVCon(testVConUuid);
    }
  });
  
  beforeEach(async () => {
    // Per-test setup
  });
  
  describe('createVCon', () => {
    it('should create a valid vCon', async () => {
      const vcon = createTestVCon();
      
      const result = await queries.createVCon(vcon);
      
      expect(result.uuid).toBeDefined();
      expect(result.uuid).toMatch(/^[0-9a-f-]{36}$/);
      testVConUuid = result.uuid;
    });
    
    it('should reject vCon without parties', async () => {
      const invalidVCon = {
        vcon: '0.4.0',
        uuid: crypto.randomUUID(),
        created_at: new Date().toISOString(),
        parties: []  // Empty - invalid
      };
      
      await expect(queries.createVCon(invalidVCon as VCon))
        .rejects
        .toThrow('at least one party');
    });
  });
});
```

### Test Naming

```typescript
// ✅ Good - Descriptive test names
it('should create a vCon with valid parties')
it('should reject vCon with invalid UUID format')
it('should return search results ordered by relevance')
it('should handle empty search results gracefully')

// ❌ Bad - Vague test names
it('works')
it('test1')
it('creates vcon')  // Not specific enough
```

### Assertions

```typescript
// ✅ Good - Specific assertions
expect(result.uuid).toBeDefined();
expect(result.uuid).toMatch(/^[0-9a-f-]{36}$/);
expect(result.parties).toHaveLength(2);
expect(result.parties[0].name).toBe('Alice');

// ❌ Bad - Vague assertions
expect(result).toBeTruthy();
expect(result.uuid).not.toBeNull();
```

***

## Git Practices

### Commit Messages

Follow [Conventional Commits](https://www.conventionalcommits.org/):

```bash
# ✅ Good
git commit -m "feat(search): add hybrid search capability"
git commit -m "fix(validation): correct analysis vendor requirement"
git commit -m "docs(api): update tools reference"
git commit -m "refactor(db): optimize search query performance"

# ❌ Bad
git commit -m "updates"
git commit -m "fix bug"
git commit -m "WIP"
```

### Commit Size

Keep commits focused and atomic:

```bash
# ✅ Good - One logical change
git commit -m "feat(search): add semantic search"

# Later...
git commit -m "docs(search): add semantic search examples"

# ❌ Bad - Multiple unrelated changes
git commit -m "Add search, fix validation, update docs, refactor utils"
```

### Branch Names

```bash
# ✅ Good
feature/semantic-search
fix/validation-error-messages
docs/api-reference-update
refactor/query-optimization

# ❌ Bad
my-feature
update
fix
```

***

## Linting and Formatting

### ESLint Configuration

The project uses ESLint with TypeScript support. Key rules:

```json
{
  "@typescript-eslint/no-explicit-any": "error",
  "@typescript-eslint/explicit-function-return-type": "warn",
  "@typescript-eslint/no-unused-vars": "error",
  "prefer-const": "error",
  "no-console": "warn"
}
```

### Running Linters

```bash
# Check for linting errors
npm run lint

# Fix auto-fixable issues
npm run lint:fix

# Format code with Prettier
npm run format

# Check formatting
npm run format:check
```

### Pre-commit Hooks

We use Husky for git hooks:

```json
{
  "husky": {
    "hooks": {
      "pre-commit": "npm run lint && npm test"
    }
  }
}
```

***

## Review Checklist

Before submitting code for review:

* [ ] Code follows style guidelines
* [ ] All tests pass
* [ ] New code has tests
* [ ] Documentation updated
* [ ] No linting errors
* [ ] TypeScript compiles
* [ ] Commit messages follow convention
* [ ] No `any` types added
* [ ] Error handling is proper
* [ ] Logging is appropriate

***

## Additional Resources

* [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/intro.html)
* [Google TypeScript Style Guide](https://google.github.io/styleguide/tsguide.html)
* [Conventional Commits](https://www.conventionalcommits.org/)
* [Clean Code JavaScript](https://github.com/ryanmcdermott/clean-code-javascript)

***

Questions about code style? Ask in GitHub Discussions or check existing code for examples.


# Documentation

Guidelines for writing and maintaining documentation for the vCon MCP Server project.

## Table of Contents

* [Documentation Types](#documentation-types)
* [Writing Style](#writing-style)
* [Markdown Standards](#markdown-standards)
* [Code Examples](#code-examples)
* [API Documentation](#api-documentation)
* [User Guides](#user-guides)
* [Build and Deploy](#build-and-deploy)

***

## Documentation Types

### 1. API Reference (`docs/api/`)

**Purpose:** Complete reference for all tools, resources, prompts, types, and schemas.

**Audience:** Developers integrating with or extending the server.

**Content:**

* All input/output parameters
* Type definitions
* Examples for every function
* Error responses
* Performance characteristics

### 2. User Guides (`docs/guide/`)

**Purpose:** Help users accomplish specific tasks.

**Audience:** End users and developers using the server.

**Content:**

* Step-by-step instructions
* Common use cases
* Troubleshooting
* Best practices

### 3. Developer Guides (`docs/development/`)

**Purpose:** Help developers contribute to the project.

**Audience:** Contributors and maintainers.

**Content:**

* Architecture explanation
* Code standards
* Testing procedures
* Plugin development

### 4. Examples (`docs/examples/`)

**Purpose:** Practical code examples and tutorials.

**Audience:** All users, especially beginners.

**Content:**

* Complete working examples
* Real-world scenarios
* Copy-paste ready code

### 5. Reference (`docs/reference/`)

**Purpose:** Technical specifications and standards.

**Audience:** Advanced developers and spec implementers.

**Content:**

* IETF vCon spec details
* Database schema
* Protocol specifications
* Migration guides

***

## Writing Style

### General Principles

1. **Be Clear** - Use simple, direct language
2. **Be Concise** - Get to the point quickly
3. **Be Consistent** - Follow established patterns
4. **Be Complete** - Cover all necessary information
5. **Be Accurate** - Keep documentation current

### Voice and Tone

* **Use active voice**: "The server validates..." not "The vCon is validated by..."
* **Use second person**: "You can create..." not "One can create..."
* **Be direct**: "Set the environment variable" not "You might want to consider setting..."
* **Be helpful**: Include context and reasoning

### Examples

✅ **Good:**

````markdown
To create a vCon, call the `create_vcon` tool with a parties array:

```typescript
const vcon = {
  vcon: '0.4.0',
  parties: [{ name: 'Alice' }]
};
````

The server validates the structure and returns the UUID.

````

❌ **Bad:**
```markdown
A vCon can be created by the user by calling the create_vcon tool. 
One should ensure that the vCon has parties otherwise it might fail.
````

***

## Markdown Standards

### Headings

Use ATX-style headings (with `#`):

```markdown
# Main Title (H1 - One per page)

## Major Section (H2)

### Subsection (H3)

#### Detail (H4)

##### Note (H5 - Rarely used)
```

**Rules:**

* Only one H1 per document
* Don't skip heading levels
* Use sentence case for headings
* Add a blank line before and after headings

### Lists

**Unordered lists:**

```markdown
- First item
- Second item
  - Nested item
  - Another nested item
- Third item
```

**Ordered lists:**

```markdown
1. First step
2. Second step
   1. Sub-step
   2. Another sub-step
3. Third step
```

**Task lists:**

```markdown
- [ ] Todo item
- [x] Completed item
- [ ] Another todo
```

### Links

**Internal links:**

```markdown
See [Architecture](./architecture.md) for details.

Jump to [Creating a Tool](#creating-a-tool) section.
```

**External links:**

```markdown
Read the [IETF vCon Spec](https://datatracker.ietf.org/doc/html/draft-ietf-vcon-vcon-core-02).
```

### Emphasis

```markdown
*Italic* or _italic_

**Bold** or __bold__

***Bold and italic***

`inline code`
```

### Tables

```markdown
| Column 1 | Column 2 | Column 3 |
|----------|----------|----------|
| Value 1  | Value 2  | Value 3  |
| Value A  | Value B  | Value C  |
```

**Alignment:**

```markdown
| Left | Center | Right |
|:-----|:------:|------:|
| L1   |   C1   |    R1 |
| L2   |   C2   |    R2 |
```

### Admonitions

Use blockquotes with emoji for callouts:

```markdown
> 📝 **Note:** Additional information that's helpful to know.

> ⚠️ **Warning:** Important information that requires attention.

> 🚨 **Critical:** Essential information that could cause problems if ignored.

> 💡 **Tip:** Helpful suggestion or best practice.

> ✅ **Success:** Confirmation or positive outcome.
```

***

## Code Examples

### Code Blocks

Always specify the language:

````markdown
```typescript
// TypeScript code
const vcon: VCon = {
  vcon: '0.4.0',
  uuid: crypto.randomUUID()
};
```

```bash
# Shell commands
npm install
npm test
```

```sql
-- SQL queries
SELECT * FROM vcons WHERE created_at > '2025-01-01';
```

```json
{
  "success": true,
  "uuid": "123e4567-e89b-12d3-a456-426614174000"
}
```
````

### Complete Examples

Provide complete, working examples:

````markdown
**Complete Example:**

```typescript
import { createClient } from '@supabase/supabase-js';
import { VCon } from './types/vcon';

// Initialize client
const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_KEY!
);

// Create vCon
async function main() {
  const vcon: VCon = {
    vcon: '0.4.0',
    uuid: crypto.randomUUID(),
    created_at: new Date().toISOString(),
    parties: [
      { name: 'Alice', mailto: 'alice@example.com' }
    ]
  };

  const { data, error } = await supabase
    .from('vcons')
    .insert(vcon)
    .select();

  if (error) {
    console.error('Error:', error);
    return;
  }

  console.log('Created:', data[0].uuid);
}

main();
```
````

### Inline Code

Use backticks for:

* Function names: `createVCon()`
* Variable names: `vconUuid`
* File names: `config.ts`
* Command names: `npm`
* Type names: `VCon`

### Terminal Commands

Show commands and expected output:

````markdown
```bash
$ npm test

> vcon-mcp-server@1.0.0 test
> vitest

✓ tests/crud.test.ts (5)
✓ tests/search.test.ts (8)

Test Files  2 passed (2)
Tests  13 passed (13)
```
````

### Multi-Step Examples

Number steps clearly:

````markdown
### Step 1: Install Dependencies

```bash
npm install @supabase/supabase-js
```

### Step 2: Configure Environment

```bash
echo "SUPABASE_URL=your-url" >> .env
echo "SUPABASE_KEY=your-key" >> .env
```

### Step 3: Initialize Client

```typescript
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(
  process.env.SUPABASE_URL!,
  process.env.SUPABASE_KEY!
);
```
````

***

## API Documentation

### Tool Documentation Template

````markdown
### tool_name

Brief description of what the tool does.

**Input Parameters:**

```typescript
{
  param1: string;              // Description
  param2?: number;             // Description (optional)
  param3: "a" | "b" | "c";    // Description (enum)
}
```

**Response:**

```typescript
{
  success: boolean;
  data?: ResultType;
  error?: string;
}
```

**Example:**

```typescript
const result = await callTool("tool_name", {
  param1: "value",
  param2: 42
});
```

**Errors:**

- `VALIDATION_ERROR` - When input validation fails
- `NOT_FOUND` - When resource doesn't exist
- `DATABASE_ERROR` - When database operation fails

**Performance:**
- Typical response time: ~100ms
- Rate limit: 100 requests/minute
````

### Type Documentation Template

````markdown
### TypeName

Description of the type and its purpose.

```typescript
interface TypeName {
  field1: string;              // Description
  field2?: number;             // Description (optional)
  field3: OtherType;          // Description
}
```

**Required Fields:**
- `field1` - Description and requirements
- `field3` - Description and requirements

**Optional Fields:**
- `field2` - Description and default value

**Examples:**

```typescript
// Minimal example
const minimal: TypeName = {
  field1: "value",
  field3: { /* ... */ }
};

// Complete example
const complete: TypeName = {
  field1: "value",
  field2: 42,
  field3: { /* ... */ }
};
```

**Validation:**
- `field1` must be non-empty
- `field2` must be positive if provided
- `field3` must be valid OtherType

**See Also:**
- [Related Type](./path.md#related-type)
- [Usage Example](../examples/example.md)
````

***

## User Guides

### Guide Structure

1. **Title** - Clear, action-oriented
2. **Introduction** - What you'll learn
3. **Prerequisites** - What's needed
4. **Steps** - Numbered, clear instructions
5. **Verification** - How to confirm success
6. **Troubleshooting** - Common issues
7. **Next Steps** - What to do next

### Example Guide Template

````markdown
# How to [Do Something]

Learn how to [accomplish goal] using [tool/feature].

## What You'll Learn

- How to [specific task 1]
- How to [specific task 2]
- Best practices for [topic]

## Prerequisites

Before starting, ensure you have:
- [ ] Item 1
- [ ] Item 2
- [ ] Item 3

## Steps

### Step 1: [First Action]

Description of what this step accomplishes.

```bash
# Commands to run
command --option value
```

**Expected output:**
```
Output that indicates success
```

### Step 2: [Second Action]

Continue with clear instructions...

## Verification

Verify your setup:

```bash
# Check command
npm test
```

You should see:
- ✅ All tests passing
- ✅ No errors in output

## Troubleshooting

### Issue: [Common Problem]

**Symptom:** Description of the problem

**Solution:**
1. Check X
2. Verify Y
3. Try Z

### Issue: [Another Problem]

**Symptom:** Description

**Solution:** Steps to fix

## Next Steps

Now that you've completed this guide:
- [Next Guide](./next-guide.md)
- [Related Topic](./related.md)
- [Advanced Usage](./advanced.md)
````

***

## Build and Deploy

### VitePress Setup

The documentation uses VitePress. To work on docs:

```bash
# Install dependencies
npm install

# Start dev server
npm run docs:dev

# Build for production
npm run docs:build

# Preview production build
npm run docs:preview
```

### Adding New Pages

1. **Create markdown file** in appropriate directory
2. **Add to sidebar** in `docs/.vitepress/config.ts`
3. **Link from index** or related pages
4. **Test locally** before committing

**Example sidebar config:**

```typescript
sidebar: {
  '/guide/': [
    {
      text: 'Getting Started',
      items: [
        { text: 'Introduction', link: '/guide/' },
        { text: 'Installation', link: '/guide/installation' },
        { text: 'Your New Page', link: '/guide/new-page' }
      ]
    }
  ]
}
```

### Documentation Workflow

1. **Create branch** for documentation changes
2. **Write/update** documentation
3. **Test locally** with `npm run docs:dev`
4. **Check links** are working
5. **Build** with `npm run docs:build`
6. **Commit** with appropriate message
7. **Create PR** for review

### Keeping Docs Updated

**When code changes:**

* [ ] Update API documentation
* [ ] Update code examples
* [ ] Update type definitions
* [ ] Update error messages
* [ ] Add migration notes if breaking

**When adding features:**

* [ ] Add to API reference
* [ ] Create user guide
* [ ] Add examples
* [ ] Update README
* [ ] Update changelog

### Documentation Review Checklist

Before submitting documentation:

* [ ] Spelling and grammar checked
* [ ] Code examples tested
* [ ] Links work correctly
* [ ] Images display properly
* [ ] Builds without errors
* [ ] Follows style guide
* [ ] No broken internal links
* [ ] No Lorem ipsum or TODO placeholders

***

## Style Guide Summary

### Do's ✅

* Use clear, simple language
* Provide complete examples
* Include error handling
* Show expected output
* Link to related content
* Keep content current
* Test all examples

### Don'ts ❌

* Use passive voice excessively
* Skip error cases
* Assume prior knowledge
* Use jargon without explanation
* Provide incomplete examples
* Leave content outdated
* Include untested code

***

## Documentation Templates

### New Feature Documentation

When adding a new feature, create:

1. **API Reference** - Complete technical specs
2. **User Guide** - How to use the feature
3. **Example** - Working code example
4. **Changelog Entry** - What changed

### Bug Fix Documentation

When fixing a bug:

1. **Update relevant docs** where bug was documented
2. **Add troubleshooting entry** if user-facing
3. **Update changelog** with fix details

### Deprecation Documentation

When deprecating a feature:

1. **Add deprecation notice** to docs
2. **Document migration path** to replacement
3. **Update changelog** with timeline
4. **Keep old docs** with "DEPRECATED" header

***

## Resources

### Tools

* **VS Code** with Markdown Preview
* **Grammarly** for spell/grammar checking
* **markdown-link-check** for broken links
* **VitePress** documentation framework

### References

* [VitePress Guide](https://vitepress.dev/guide/what-is-vitepress)
* [Markdown Guide](https://www.markdownguide.org/)
* [Google Developer Documentation Style Guide](https://developers.google.com/style)
* [Write the Docs](https://www.writethedocs.org/)

***

## Questions?

* Check existing documentation for examples
* Ask in GitHub Discussions
* Review recent PRs for documentation changes
* Contact documentation maintainers

**Remember:** Good documentation is as important as good code! 📚


# Overview

Deploy the vCon MCP Server to production environments.

## Overview

This guide covers:

* Production deployment strategies
* Security best practices
* Performance optimization
* Platform-specific guides

## Quick Deployment Options

### Option 1: Docker (Recommended)

```bash
# Pull from ECR Public
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main

# Run container
docker run -d -p 3000:3000 \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

Or build locally:

```bash
docker build -t vcon-mcp .
docker run -d -p 3000:3000 --env-file .env vcon-mcp
```

### Option 2: Node.js Direct

```bash
# Build
npm run build

# Run
node dist/index.js
```

### Option 3: Kubernetes

```bash
# Apply configuration
kubectl apply -f k8s/deployment.yaml
```

## Documentation Sections

### [Production Setup](/deployment/production)

* Environment configuration
* Process management
* Logging and monitoring
* Backup strategies

### [Security](/deployment/security)

* Authentication and authorization
* API security
* Database security
* Network security
* Compliance considerations

### [Performance](/deployment/performance)

* Database optimization
* Caching strategies
* Query tuning
* Load testing
* Scaling strategies

### [Docker Deployment](/deployment/docker)

* Dockerfile configuration
* Docker Compose setup
* Multi-stage builds
* Volume management

### [Kubernetes Deployment](/deployment/kubernetes)

* Deployment manifests
* Service configuration
* Ingress setup
* Secrets management

### [Cloud Providers](/deployment/cloud)

* AWS deployment
* Google Cloud deployment
* Azure deployment
* Heroku deployment

### [Self-Hosted Supabase](/deployment/self-hosted-supabase)

* Complete self-hosted deployment
* Docker Compose stack with all services
* Kong API Gateway configuration
* Embedding job scheduling with Ofelia

## Prerequisites

* Node.js 18 or higher
* PostgreSQL 14+ (or Supabase account)
* Sufficient resources (see requirements)

## System Requirements

### Minimum

* **CPU**: 1 core
* **RAM**: 512 MB
* **Disk**: 1 GB
* **Database**: PostgreSQL 14+

### Recommended

* **CPU**: 2+ cores
* **RAM**: 2 GB+
* **Disk**: 10 GB+
* **Database**: PostgreSQL 15+ with pgvector

## Environment Variables

```bash
# Required
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key

# Optional
SUPABASE_SERVICE_ROLE_KEY=your-service-key
VCON_PLUGINS_PATH=./plugins
VCON_LICENSE_KEY=your-license-key
NODE_ENV=production

# Tool Categories (see below)
MCP_TOOLS_PROFILE=full
```

## Tool Categories for Deployment

Control which tools are available based on deployment type:

### Deployment Profiles

| Profile    | Categories                                               | Use Case                                     |
| ---------- | -------------------------------------------------------- | -------------------------------------------- |
| `full`     | All                                                      | Development, full access                     |
| `readonly` | read, schema                                             | Read-only API, dashboards                    |
| `user`     | read, write, schema                                      | End-user facing applications                 |
| `admin`    | read, analytics, infra, schema                           | Admin/monitoring dashboards                  |
| `minimal`  | read, write                                              | Basic CRUD microservice                      |
| `public`   | read, schema, minus `vcon_aggregate` and `vcon_taxonomy` | Hosted public datasets; also filters prompts |

### Configuration Options

```bash
# Option 1: Use a preset profile
MCP_TOOLS_PROFILE=readonly

# Option 2: Enable specific categories
MCP_ENABLED_CATEGORIES=read,write,schema

# Option 3: Disable specific categories
MCP_DISABLED_CATEGORIES=analytics,infra

# Option 4: Disable individual tools
MCP_DISABLED_TOOLS=delete_vcon,analyze_query
```

### Example: Read-Only Deployment

```bash
# Docker run with read-only profile
docker run -d -p 3000:3000 \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_TOOLS_PROFILE=readonly \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

### Example: User-Facing with Restricted Delete

```bash
# Allow CRUD but prevent deletion
docker run -d -p 3000:3000 \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_TOOLS_PROFILE=user \
  -e MCP_DISABLED_TOOLS=delete_vcon \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

## Health Checks

The server provides health check endpoints:

```bash
# Basic health check (REST API)
curl http://localhost:3000/api/v1/health
```

## Monitoring

Key metrics to monitor:

* Request latency
* Database connection pool
* Memory usage
* Error rates
* Search performance

## Next Steps

1. Review [Security](/deployment/security) best practices
2. Set up [Performance](/deployment/performance) monitoring
3. Choose your deployment platform
4. Configure backups and disaster recovery


# Production Setup

Production deployment considerations for vCon MCP Server.

## Environment Variables

### Required

```bash
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
SUPABASE_ANON_KEY=your-anon-key
MCP_HTTP_STATELESS=true  # Required for multi-instance deployments
```

### Recommended

```bash
NODE_ENV=production
MCP_TOOLS_PROFILE=full       # or: readonly, user, admin, minimal, public
LOG_LEVEL=info
OTEL_ENABLED=true            # Enable observability
OPENAI_API_KEY=your-key      # For embeddings
REDIS_URL=redis://host:6379  # For caching
```

## Multi-Instance Deployment

```yaml
# docker-compose.prod.yml
version: '3.8'
services:
  vcon-mcp:
    image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    deploy:
      replicas: 3
    environment:
      - MCP_HTTP_STATELESS=true
    env_file:
      - .env.production
    healthcheck:
      test: ["CMD", "wget", "--spider", "-q", "http://127.0.0.1:3000/api/v1/health"]
      interval: 30s
      timeout: 10s
      retries: 3
```

> **Important**: `MCP_HTTP_STATELESS=true` is required for multi-instance deployments.

## Resource Recommendations

| Workload    | CPU  | Memory | Replicas |
| ----------- | ---- | ------ | -------- |
| Development | 0.25 | 256Mi  | 1        |
| Small       | 0.5  | 512Mi  | 1-2      |
| Medium      | 1    | 1Gi    | 2-3      |
| Large       | 2    | 2Gi    | 3+       |

## Database tuning for large corpora

The Supabase CLI starts Postgres with development defaults: `shared_buffers = 128MB`, `effective_cache_size = 128MB`, `effective_io_concurrency = 1`. Past a few hundred thousand vCons, keyword search (`search_vcons_keyword`, REST `/vcons/search/content`, MCP `search_vcons_content`) starts returning `canceling statement due to statement timeout`. The `authenticated` role has `statement_timeout = 8s`.

The query itself is not the problem. It ranks every match, and each match's `body_tsvector` is stored out of line (TOAST). While those pages are cached, a common term on \~260k vCons takes 1–3 s. Cold, the same search needs one random read per match: measured at 22–46 s for terms matching 6k–56k analysis and dialog rows (CON-1071). With 128MB of shared buffers and any concurrent load (ingest, embedding backfill), the working set never stays cached.

For a deployment on a dedicated host, size Postgres to the machine. On a 16 GB host:

1. **Memory.** Set these in `supabase/config.toml`; the CLI applies them on `supabase start`:

   ```toml
   [db.settings]
   shared_buffers = "4GB"          # ~25% of RAM; should hold the search working set
   effective_cache_size = "10GB"   # ~65% of RAM
   maintenance_work_mem = "512MB"
   ```

   Leave `work_mem` at its default. The CLI's database container has a 64 MB `/dev/shm`, so a larger `work_mem` makes parallel queries fail with `could not resize shared memory segment ... No space left on device`.
2. **SSD planner settings.** `[db.settings]` doesn't accept these, so set them as the superuser over the container's socket:

   ```bash
   docker exec supabase_db_vcon-mcp psql -U supabase_admin -d postgres \
     -c "alter system set effective_io_concurrency = 200" \
     -c "alter system set random_page_cost = 1.1" \
     -c "select pg_reload_conf()"
   ```
3. **Keep the cache warm across restarts.** Run `create extension if not exists pg_prewarm;` as `supabase_admin`. Then append `pg_prewarm` to `shared_preload_libraries` and restart the database container. Autoprewarm records the buffer contents every few minutes and reloads them at startup. `shared_preload_libraries` replaces the image's list rather than adding to it: read the current value with `show shared_preload_libraries`, append `, pg_prewarm`, and write the list as **one** plain quoted string. Dollar-quoting the value turns the whole list into a single library name, and Postgres will not start.
4. **Warm the working set once** after tuning or a bulk load:

   ```sql
   select sum(pg_prewarm(r)) from (
     select c.oid::regclass r from pg_class c
      where c.relname in ('analysis','dialog','vcons','parties') and c.relnamespace = 'public'::regnamespace
     union all
     select c.reltoastrelid::regclass from pg_class c
      where c.relname in ('analysis','dialog','vcons') and c.relnamespace = 'public'::regnamespace
     union all
     select i.indexrelid::regclass from pg_index i join pg_class c on c.oid = i.indrelid
      where c.relname in ('analysis','dialog','vcons','parties','vcon_tags_mv') and c.relnamespace = 'public'::regnamespace
   ) x;
   ```

Measured on 259,596 vCons, a 16 GB host and gp3 storage, with an embedding backfill running: after these steps, keyword searches through the REST API took 0.8–2.4 s. The worst case was "call", which matches \~520k rows, at 5.3 s. Before, they timed out.

Tag-filtered searches also need `vcon_tags_mv` refreshed. Self-hosted boxes have nothing that does this automatically; see [pg\_cron setup](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/setup-pg-cron-guide.md).

## Health Check

```bash
curl http://localhost:3000/api/v1/health
```

## Graceful Shutdown

The server handles SIGTERM gracefully - completes in-flight requests before exiting:

```bash
docker stop --time=30 vcon-mcp
```

## Next Steps

* [Docker Deployment](/deployment/docker)
* [Kubernetes Deployment](/deployment/kubernetes)
* [Cloud Providers](/deployment/cloud)


# Security

Security considerations specific to vCon MCP Server.

## Supabase Keys

| Key                         | Access Level              | Use Case                     |
| --------------------------- | ------------------------- | ---------------------------- |
| `SUPABASE_SERVICE_ROLE_KEY` | Full access, bypasses RLS | Server-side deployments      |
| `SUPABASE_ANON_KEY`         | Restricted, RLS enforced  | Client-facing with user auth |

**Recommendation**: Use `SUPABASE_SERVICE_ROLE_KEY` for trusted server deployments.

## Tool Access Control

### Profiles

Control which MCP tools are available:

```bash
MCP_TOOLS_PROFILE=readonly   # Read-only operations
MCP_TOOLS_PROFILE=user       # CRUD without admin ops
MCP_TOOLS_PROFILE=full       # All tools (default)
```

### Disable Specific Tools

```bash
MCP_DISABLED_TOOLS=delete_vcon,execute_sql
```

### Available Profiles

| Profile    | Description                                                                                                                                         |
| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| `full`     | All tools enabled (default)                                                                                                                         |
| `readonly` | Read-only operations only                                                                                                                           |
| `user`     | CRUD without admin operations                                                                                                                       |
| `admin`    | Full access including schema changes                                                                                                                |
| `minimal`  | Basic operations only                                                                                                                               |
| `public`   | Read and search tools for a hosted public dataset; hides database internals, analytics, deployment-shaped rollups, and the prompts that assume them |

## OAuth for MCP Connectors

claude.ai and the Claude Desktop chat add remote MCP servers as custom connectors, and those only sign in with OAuth 2.1. Claude Code and scripts keep using a static bearer token from `API_KEYS` or `API_KEYS_READONLY`; the server checks static keys first, so turning OAuth on changes nothing for them.

vcon-mcp is the **resource server** only. An external authorization server handles sign-in, PKCE, dynamic client registration and token issuance. The steps below use Supabase OAuth Server; any issuer that signs JWTs and publishes `<issuer>/.well-known/jwks.json` works the same way.

### What the server does

| Path                                                                                    | Auth | Response                                                                                                                          |
| --------------------------------------------------------------------------------------- | ---- | --------------------------------------------------------------------------------------------------------------------------------- |
| `/.well-known/oauth-protected-resource` and `/.well-known/oauth-protected-resource/mcp` | none | RFC 9728 metadata naming `OAUTH_ISSUER` as the authorization server                                                               |
| `/.well-known/oauth-authorization-server`                                               | none | `302` to the issuer's RFC 8414 metadata                                                                                           |
| `/oauth/consent`                                                                        | none | Consent page, when `OAUTH_CONSENT_ANON_KEY` is set                                                                                |
| `/mcp` with no or bad token                                                             |      | `401` with `WWW-Authenticate: Bearer resource_metadata="<origin>/.well-known/oauth-protected-resource/mcp"`                       |
| `/mcp` with an OAuth token                                                              | JWT  | Checked on every request: signature against the issuer JWKS, `iss`, `exp`, `aud` equal to `OAUTH_RESOURCE`, optional email domain |

The REST API (`/api/v1`) still takes static keys only.

### Environment

```bash
OAUTH_ISSUER=https://<project-ref>.supabase.co/auth/v1
OAUTH_RESOURCE=https://mcp.example.com/mcp     # the exact URL users paste into the connector
OAUTH_READONLY=true                             # default; false gives OAuth sessions write tools
OAUTH_ALLOWED_EMAIL_DOMAINS=example.com         # optional
OAUTH_CONSENT_ANON_KEY=<publishable key>        # Supabase publishable (anon) key, safe to expose
OAUTH_CONSENT_PROVIDERS=email                   # or google, or email,google
```

With OAuth on, `API_KEYS` may be empty: an OAuth-only deployment gets `401`s that point at the metadata instead of the "no API keys configured" `503`.

### Supabase setup

1. **Signing keys.** Authentication > JWT Keys: move to asymmetric keys (ES256 or RS256). The server verifies against the JWKS and cannot check legacy HS256 tokens.
2. **OAuth Server.** Authentication > OAuth Server: enable it, turn on dynamic client registration (claude.ai registers itself), and set the Authorization Path to `/oauth/consent`. Set the project's Site URL to the MCP server's origin (`https://mcp.example.com`) so the consent link lands on this server.
3. **Audience.** Supabase access tokens carry `aud: "authenticated"`, which the server rejects. Add a Custom Access Token hook that sets `aud` to `OAUTH_RESOURCE` on OAuth-issued tokens (those carrying `client_id`):

   ```sql
   create or replace function public.mcp_access_token_hook(event jsonb)
   returns jsonb language plpgsql stable as $$
   begin
     if event->'claims' ? 'client_id' then
       event := jsonb_set(event, '{claims,aud}', to_jsonb('https://mcp.example.com/mcp'::text));
     end if;
     return event;
   end $$;
   grant execute on function public.mcp_access_token_hook to supabase_auth_admin;
   revoke execute on function public.mcp_access_token_hook from authenticated, anon, public;
   ```

   Then select it under Authentication > Hooks > Custom Access Token.
4. **Sign-in.** `OAUTH_CONSENT_PROVIDERS` picks what the consent page offers.
   * `email` (default): a six-digit emailed code, existing users only (`create_user: false`). Needs working SMTP, and `{{ .Token }}` in the Magic Link email template.
   * A Supabase external provider such as `google`: PKCE redirect through the provider, no SMTP. Enable the provider in Supabase, with its callback at `<issuer>/callback`. With signups disabled, create each allowed user first (admin API, verified email); Supabase links the Google identity to that user on first sign-in.

### Self-hosted Supabase

The same steps apply, set through the auth container's environment instead of the dashboard. The OAuth server is in `supabase/gotrue` from v2.180; use v2.186 or later, which stores and enforces the `token_endpoint_auth_method` that dynamically registered clients declare.

```bash
GOTRUE_JWT_ISSUER=https://mcp.example.com/auth/v1
GOTRUE_SITE_URL=https://mcp.example.com
API_EXTERNAL_URL=https://mcp.example.com/auth/v1
GOTRUE_OAUTH_SERVER_ENABLED=true
GOTRUE_OAUTH_SERVER_AUTHORIZATION_PATH=/oauth/consent
GOTRUE_OAUTH_SERVER_ALLOW_DYNAMIC_REGISTRATION=true
GOTRUE_JWT_KEYS='[<ES256 signing JWK>, <existing HS256 secret as an oct verify-only JWK>]'
GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_ENABLED=true
GOTRUE_HOOK_CUSTOM_ACCESS_TOKEN_URI=pg-functions://postgres/public/mcp_access_token_hook
```

Keeping the old HS256 secret in `GOTRUE_JWT_KEYS` as verify-only keeps the existing anon and service-role keys valid, so PostgREST and vcon-mcp's database access are unaffected.

MCP clients call the authorization server without a Supabase `apikey`, which the stock Kong gateway requires. Route the OAuth paths from the reverse proxy straight to the auth container (port 9999) with `/auth/v1` stripped: `/auth/v1/oauth/*`, `/auth/v1/.well-known/*`, then `/auth/v1/otp` and `/auth/v1/verify` for email sign-in, or `/auth/v1/authorize`, `/auth/v1/callback` and `/auth/v1/token` for a provider such as Google, plus `/.well-known/oauth-authorization-server/auth/v1` rewritten to `/.well-known/oauth-authorization-server`. Give these routes priority over the vcon-mcp route. Nothing else on the auth API needs to be public.

### Connect a client

In claude.ai: Settings > Connectors > Add custom connector, URL `https://mcp.example.com/mcp`. Leave the OAuth client ID and secret empty; the client registers itself. Sign in, enter the emailed code, approve. The connector then shows in Claude Desktop chat as well.

### Checks

```bash
curl -s https://mcp.example.com/.well-known/oauth-protected-resource/mcp
curl -si -X POST https://mcp.example.com/mcp | grep -i www-authenticate
```

## Container Security

The Docker image includes security defaults:

* Runs as non-root user (`vcon`, uid 1001)
* Minimal Alpine base image
* No shell access by default

## Best Practices

* Store secrets in environment variables or secret managers, not in code
* Use HTTPS in production (via reverse proxy)
* Enable `MCP_HTTP_STATELESS=true` for multi-instance deployments
* Restrict tool profiles based on use case

## Next Steps

* [Production Setup](/deployment/production)
* [Docker Deployment](/deployment/docker)


# Performance

Performance considerations for vCon MCP Server.

## Resource Recommendations

| Workload           | CPU  | Memory | Replicas |
| ------------------ | ---- | ------ | -------- |
| Development        | 0.25 | 256Mi  | 1        |
| Production (small) | 0.5  | 512Mi  | 2        |
| Production (large) | 1    | 1Gi    | 3+       |

## Multi-Instance Deployments

Enable stateless mode for horizontal scaling:

```bash
MCP_HTTP_STATELESS=true
```

## Embedding Performance

Process embeddings in batches to avoid rate limits:

```bash
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-key \
  -e OPENAI_API_KEY=your-key \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main \
  script embed-vcons --batch-size=50 --delay=100
```

## Search Performance

| Search Type | Speed  | Use Case             |
| ----------- | ------ | -------------------- |
| Full-text   | Fast   | Keyword matching     |
| Semantic    | Slower | Meaning-based search |
| Hybrid      | Medium | Best of both         |

## Caching (Optional)

Enable Redis for caching:

```bash
REDIS_URL=redis://localhost:6379
```

## Observability

Enable OpenTelemetry for performance monitoring:

```bash
OTEL_ENABLED=true
OTEL_ENDPOINT=http://jaeger:4318
```

## Next Steps

* [Docker Deployment](/deployment/docker)
* [Production Setup](/deployment/production)


# Docker

Deploy the vCon MCP Server using Docker for consistent, portable deployments.

## Quick Start

### Pull from ECR Public

```bash
# Pull the latest image
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main

# Run the server
docker run -p 3000:3000 \
  -e SUPABASE_URL=https://your-project.supabase.co \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

### Build Locally

```bash
# Clone and build
git clone https://github.com/vcon-dev/vcon-mcp.git
cd vcon-mcp
docker build -t vcon-mcp .

# Run
docker run -p 3000:3000 --env-file .env vcon-mcp
```

## Image Tags

| Tag          | Description                            |
| ------------ | -------------------------------------- |
| `main`       | Latest stable build from main branch   |
| `main-<sha>` | Specific commit (e.g., `main-abc1234`) |
| `1.2.3`      | Semantic version release               |
| `1.2`        | Minor version (latest patch)           |
| `1`          | Major version (latest minor/patch)     |

## Running the Server

### Basic Usage

```bash
# Start the MCP server (default)
docker run -p 3000:3000 \
  -e SUPABASE_URL=https://your-project.supabase.co \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

### With Environment File

```bash
# Create .env file
cat > .env << EOF
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
SUPABASE_ANON_KEY=your-anon-key
MCP_TRANSPORT=http
MCP_HTTP_HOST=0.0.0.0
MCP_HTTP_PORT=3000
MCP_HTTP_STATELESS=true
MCP_TOOLS_PROFILE=full
EOF

# Run with env file
docker run -p 3000:3000 --env-file .env public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

### Multi-Client Support

For multiple clients to connect simultaneously, enable stateless mode:

```bash
docker run -p 3000:3000 \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

> **Note**: Without `MCP_HTTP_STATELESS=true`, only one MCP client can connect at a time due to session tracking limitations in the MCP SDK.

## Running Scripts

The Docker image includes all utility scripts from the `/scripts` directory:

### List Available Scripts

```bash
docker run --rm public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main help
```

### Run a Script

```bash
# Check database status
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main script check-db-status

# Sync vCons
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main script sync-all

# Generate embeddings
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e OPENAI_API_KEY=your-openai-key \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main script embed-vcons --provider=openai
```

### Run TypeScript Directly

```bash
# Run any TypeScript file
docker run --rm \
  -e SUPABASE_URL=your-url \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -v $(pwd)/my-script.ts:/app/my-script.ts \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main tsx /app/my-script.ts
```

## Environment Variables

### Required

| Variable                    | Description                                                    |
| --------------------------- | -------------------------------------------------------------- |
| `SUPABASE_URL`              | Your Supabase project URL                                      |
| `SUPABASE_SERVICE_ROLE_KEY` | Supabase service role key (full database access, bypasses RLS) |
| `SUPABASE_ANON_KEY`         | Supabase anonymous key (restricted access with RLS)            |

> **Note:** You need at least one of `SUPABASE_SERVICE_ROLE_KEY` or `SUPABASE_ANON_KEY`. The service role key is recommended for server-side deployments as it provides full database access.

### MCP Transport

| Variable             | Default   | Description                            |
| -------------------- | --------- | -------------------------------------- |
| `MCP_TRANSPORT`      | `http`    | Transport type: `http` or `stdio`      |
| `MCP_HTTP_HOST`      | `0.0.0.0` | HTTP host to bind                      |
| `MCP_HTTP_PORT`      | `3000`    | HTTP port to listen on                 |
| `MCP_HTTP_STATELESS` | `false`   | Enable stateless mode for multi-client |
| `MCP_HTTP_JSON_ONLY` | `false`   | Disable SSE, JSON responses only       |

### Tool Configuration

| Variable                 | Default | Description                                                      |
| ------------------------ | ------- | ---------------------------------------------------------------- |
| `MCP_TOOLS_PROFILE`      | `full`  | Preset: `full`, `readonly`, `user`, `admin`, `minimal`, `public` |
| `MCP_ENABLED_CATEGORIES` | (all)   | Comma-separated: `read,write,schema,analytics,infra`             |
| `MCP_DISABLED_TOOLS`     | (none)  | Comma-separated tool names to disable                            |

### Optional Services

| Variable         | Description                                            |
| ---------------- | ------------------------------------------------------ |
| `REDIS_URL`      | Redis URL for caching (e.g., `redis://localhost:6379`) |
| `OPENAI_API_KEY` | OpenAI API key for embeddings                          |
| `OTEL_ENABLED`   | Enable OpenTelemetry (`true`/`false`)                  |
| `OTEL_ENDPOINT`  | OTLP collector endpoint                                |

## Docker Compose

### Basic Setup

```yaml
# docker-compose.yml
version: '3.8'

services:
  vcon-mcp:
    image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    ports:
      - "3000:3000"
    environment:
      - SUPABASE_URL=${SUPABASE_URL}
      - SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
      - SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - MCP_HTTP_STATELESS=true
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/v1/health"]
      interval: 30s
      timeout: 10s
      retries: 3
```

### With Redis Caching

```yaml
version: '3.8'

services:
  vcon-mcp:
    image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    ports:
      - "3000:3000"
    environment:
      - SUPABASE_URL=${SUPABASE_URL}
      - SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
      - SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - REDIS_URL=redis://redis:6379
      - MCP_HTTP_STATELESS=true
    depends_on:
      - redis

  redis:
    image: redis:7-alpine
    volumes:
      - redis-data:/data

volumes:
  redis-data:
```

### With Observability

```yaml
version: '3.8'

services:
  vcon-mcp:
    image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    ports:
      - "3000:3000"
    environment:
      - SUPABASE_URL=${SUPABASE_URL}
      - SUPABASE_SERVICE_ROLE_KEY=${SUPABASE_SERVICE_ROLE_KEY}
      - SUPABASE_ANON_KEY=${SUPABASE_ANON_KEY}
      - MCP_HTTP_STATELESS=true
      - OTEL_ENABLED=true
      - OTEL_EXPORTER_TYPE=otlp
      - OTEL_ENDPOINT=http://jaeger:4318

  jaeger:
    image: jaegertracing/all-in-one:latest
    ports:
      - "16686:16686"  # Jaeger UI
      - "4318:4318"    # OTLP HTTP
```

## Connecting to Local Services

When running in Docker and connecting to services on your host machine (like local Supabase), use `host.docker.internal`:

```bash
# Instead of localhost or 127.0.0.1
docker run -p 3000:3000 \
  -e SUPABASE_URL=http://host.docker.internal:54321 \
  -e SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  -e SUPABASE_ANON_KEY=your-anon-key \
  -e MCP_HTTP_STATELESS=true \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
```

> **Note**: `host.docker.internal` works on Docker Desktop (Mac/Windows). On Linux, use `--network host` or the host's actual IP.

## Health Checks

The image includes a built-in health check:

```bash
# Check health via REST API
curl http://localhost:3000/api/v1/health

# Docker health status
docker inspect --format='{{.State.Health.Status}}' <container-id>
```

## Production Deployment

### Kubernetes

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vcon-mcp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vcon-mcp
  template:
    metadata:
      labels:
        app: vcon-mcp
    spec:
      containers:
      - name: vcon-mcp
        image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
        ports:
        - containerPort: 3000
        env:
        - name: SUPABASE_URL
          valueFrom:
            secretKeyRef:
              name: vcon-secrets
              key: supabase-url
        - name: SUPABASE_SERVICE_ROLE_KEY
          valueFrom:
            secretKeyRef:
              name: vcon-secrets
              key: supabase-service-role-key
        - name: SUPABASE_ANON_KEY
          valueFrom:
            secretKeyRef:
              name: vcon-secrets
              key: supabase-anon-key
        - name: MCP_HTTP_STATELESS
          value: "true"
        livenessProbe:
          httpGet:
            path: /api/v1/health
            port: 3000
          initialDelaySeconds: 10
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /api/v1/health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 10
```

### AWS ECS

```json
{
  "family": "vcon-mcp",
  "containerDefinitions": [
    {
      "name": "vcon-mcp",
      "image": "public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main",
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {"name": "MCP_HTTP_STATELESS", "value": "true"}
      ],
      "secrets": [
        {"name": "SUPABASE_URL", "valueFrom": "arn:aws:secretsmanager:..."},
        {"name": "SUPABASE_SERVICE_ROLE_KEY", "valueFrom": "arn:aws:secretsmanager:..."},
        {"name": "SUPABASE_ANON_KEY", "valueFrom": "arn:aws:secretsmanager:..."}
      ],
      "healthCheck": {
        "command": ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api/v1/health || exit 1"],
        "interval": 30,
        "timeout": 10,
        "retries": 3
      }
    }
  ]
}
```

## Image Details

* **Base Image**: Node.js 20 Alpine
* **Size**: \~680 MB
* **Platforms**: linux/amd64, linux/arm64
* **User**: Non-root (`vcon:nodejs`)
* **Working Directory**: `/app`

## Troubleshooting

### Container Exits Immediately

Check logs for missing environment variables:

```bash
docker logs <container-id>
```

Common causes:

* Missing `SUPABASE_URL` or Supabase keys (`SUPABASE_SERVICE_ROLE_KEY` / `SUPABASE_ANON_KEY`)
* Invalid credentials

### Connection Refused to Database

If connecting to local Supabase:

```bash
# Use host.docker.internal instead of localhost
-e SUPABASE_URL=http://host.docker.internal:54321
```

### Multiple Clients Failing

Enable stateless mode:

```bash
-e MCP_HTTP_STATELESS=true
```

### View Container Logs

```bash
# Follow logs
docker logs -f <container-id>

# Last 100 lines
docker logs --tail 100 <container-id>
```

## Building Custom Images

```dockerfile
FROM public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main

# Add custom scripts
COPY my-scripts/ /app/scripts/

# Add custom environment defaults
ENV MY_CUSTOM_VAR=value
```

Build and run:

```bash
docker build -t my-vcon-mcp .
docker run -p 3000:3000 --env-file .env my-vcon-mcp
```


# Kubernetes

Deploy the vCon MCP Server to Kubernetes.

## Quick Start

### Create Secrets

```bash
kubectl create secret generic vcon-mcp-secrets \
  --from-literal=SUPABASE_URL=https://your-project.supabase.co \
  --from-literal=SUPABASE_SERVICE_ROLE_KEY=your-service-role-key \
  --from-literal=SUPABASE_ANON_KEY=your-anon-key \
  --from-literal=OPENAI_API_KEY=your-openai-key
```

### Deploy

```yaml
# vcon-mcp.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vcon-mcp
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vcon-mcp
  template:
    metadata:
      labels:
        app: vcon-mcp
    spec:
      containers:
      - name: vcon-mcp
        image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
        ports:
        - containerPort: 3000
        env:
        - name: MCP_HTTP_STATELESS
          value: "true"
        - name: MCP_TOOLS_PROFILE
          value: "full"
        envFrom:
        - secretRef:
            name: vcon-mcp-secrets
        resources:
          requests:
            memory: "256Mi"
            cpu: "100m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /api/v1/health
            port: 3000
          initialDelaySeconds: 10
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /api/v1/health
            port: 3000
          initialDelaySeconds: 5
          periodSeconds: 10
---
apiVersion: v1
kind: Service
metadata:
  name: vcon-mcp
spec:
  selector:
    app: vcon-mcp
  ports:
  - port: 80
    targetPort: 3000
```

```bash
kubectl apply -f vcon-mcp.yaml
```

## Environment Variables

Key configuration for Kubernetes deployments:

| Variable                    | Required    | Description                                              |
| --------------------------- | ----------- | -------------------------------------------------------- |
| `SUPABASE_URL`              | Yes         | Supabase project URL                                     |
| `SUPABASE_SERVICE_ROLE_KEY` | Yes\*       | Service role key (bypasses RLS)                          |
| `SUPABASE_ANON_KEY`         | Yes\*       | Anonymous key (uses RLS)                                 |
| `MCP_HTTP_STATELESS`        | Recommended | Set `true` for multi-replica deployments                 |
| `MCP_TOOLS_PROFILE`         | No          | `full`, `readonly`, `user`, `admin`, `minimal`, `public` |
| `MCP_DISABLED_TOOLS`        | No          | Comma-separated list of tools to disable                 |
| `OPENAI_API_KEY`            | No          | For embedding generation                                 |

\*At least one Supabase key required

## Running Scripts as Jobs

### One-time Job

```yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: vcon-check-db
spec:
  ttlSecondsAfterFinished: 300
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: script
        image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
        command: ["script", "check-db-status"]
        envFrom:
        - secretRef:
            name: vcon-mcp-secrets
```

### Scheduled Embeddings Sync

```yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: vcon-embeddings
spec:
  schedule: "0 */6 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: embeddings
            image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
            command: ["script", "embed-vcons", "--provider=openai", "--limit=500"]
            envFrom:
            - secretRef:
                name: vcon-mcp-secrets
```

## Resource Recommendations

| Workload           | Replicas | CPU Request | Memory Request |
| ------------------ | -------- | ----------- | -------------- |
| Development        | 1        | 100m        | 256Mi          |
| Production (small) | 2        | 250m        | 512Mi          |
| Production (large) | 3+       | 500m        | 1Gi            |

## Troubleshooting

```bash
# Check pod status
kubectl get pods -l app=vcon-mcp

# View logs
kubectl logs -l app=vcon-mcp -f

# Port forward for testing
kubectl port-forward svc/vcon-mcp 3000:80
curl http://localhost:3000/api/v1/health
```

## Next Steps

* [Cloud Providers](/deployment/cloud) - Managed Kubernetes (EKS, GKE, AKS)
* [Docker Deployment](/deployment/docker) - Container basics
* [Production Setup](/deployment/production) - Production configuration


# Cloud Providers

Deploy vCon MCP Server to major cloud providers with managed container services.

## AWS

### Amazon ECS (Fargate)

#### Task Definition

```json
{
  "family": "vcon-mcp",
  "networkMode": "awsvpc",
  "requiresCompatibilities": ["FARGATE"],
  "cpu": "512",
  "memory": "1024",
  "executionRoleArn": "arn:aws:iam::YOUR_ACCOUNT:role/ecsTaskExecutionRole",
  "taskRoleArn": "arn:aws:iam::YOUR_ACCOUNT:role/vconMcpTaskRole",
  "containerDefinitions": [
    {
      "name": "vcon-mcp",
      "image": "public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main",
      "essential": true,
      "portMappings": [
        {
          "containerPort": 3000,
          "protocol": "tcp"
        }
      ],
      "environment": [
        {"name": "MCP_HTTP_STATELESS", "value": "true"},
        {"name": "MCP_HTTP_HOST", "value": "0.0.0.0"},
        {"name": "MCP_HTTP_PORT", "value": "3000"},
        {"name": "MCP_TOOLS_PROFILE", "value": "full"}
      ],
      "secrets": [
        {
          "name": "SUPABASE_URL",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:YOUR_ACCOUNT:secret:vcon-mcp/supabase-url"
        },
        {
          "name": "SUPABASE_SERVICE_ROLE_KEY",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:YOUR_ACCOUNT:secret:vcon-mcp/supabase-service-role-key"
        },
        {
          "name": "SUPABASE_ANON_KEY",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:YOUR_ACCOUNT:secret:vcon-mcp/supabase-anon-key"
        },
        {
          "name": "OPENAI_API_KEY",
          "valueFrom": "arn:aws:secretsmanager:us-east-1:YOUR_ACCOUNT:secret:vcon-mcp/openai-api-key"
        }
      ],
      "healthCheck": {
        "command": ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://127.0.0.1:3000/api/v1/health || exit 1"],
        "interval": 30,
        "timeout": 10,
        "retries": 3,
        "startPeriod": 15
      },
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/vcon-mcp",
          "awslogs-region": "us-east-1",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ]
}
```

#### Create Service with CLI

```bash
# Create secrets
aws secretsmanager create-secret \
  --name vcon-mcp/supabase-url \
  --secret-string "https://your-project.supabase.co"

aws secretsmanager create-secret \
  --name vcon-mcp/supabase-service-role-key \
  --secret-string "your-service-role-key"

aws secretsmanager create-secret \
  --name vcon-mcp/supabase-anon-key \
  --secret-string "your-anon-key"

# Register task definition
aws ecs register-task-definition --cli-input-json file://task-definition.json

# Create service
aws ecs create-service \
  --cluster your-cluster \
  --service-name vcon-mcp \
  --task-definition vcon-mcp \
  --desired-count 2 \
  --launch-type FARGATE \
  --network-configuration "awsvpcConfiguration={subnets=[subnet-xxx],securityGroups=[sg-xxx],assignPublicIp=ENABLED}"
```

#### CloudFormation Template

```yaml
# cloudformation-vcon-mcp.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: vCon MCP Server on ECS Fargate

Parameters:
  VpcId:
    Type: AWS::EC2::VPC::Id
  SubnetIds:
    Type: List<AWS::EC2::Subnet::Id>
  SupabaseUrl:
    Type: String
    NoEcho: true
  SupabaseServiceRoleKey:
    Type: String
    NoEcho: true
  SupabaseAnonKey:
    Type: String
    NoEcho: true

Resources:
  ECSCluster:
    Type: AWS::ECS::Cluster
    Properties:
      ClusterName: vcon-mcp-cluster

  LogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: /ecs/vcon-mcp
      RetentionInDays: 30

  TaskExecutionRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: ecs-tasks.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
      Policies:
        - PolicyName: SecretsAccess
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - secretsmanager:GetSecretValue
                Resource: !Sub 'arn:aws:secretsmanager:${AWS::Region}:${AWS::AccountId}:secret:vcon-mcp/*'

  TaskDefinition:
    Type: AWS::ECS::TaskDefinition
    Properties:
      Family: vcon-mcp
      NetworkMode: awsvpc
      RequiresCompatibilities:
        - FARGATE
      Cpu: '512'
      Memory: '1024'
      ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
      ContainerDefinitions:
        - Name: vcon-mcp
          Image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
          PortMappings:
            - ContainerPort: 3000
          Environment:
            - Name: MCP_HTTP_STATELESS
              Value: 'true'
          Secrets:
            - Name: SUPABASE_URL
              ValueFrom: !Ref SupabaseUrlSecret
            - Name: SUPABASE_SERVICE_ROLE_KEY
              ValueFrom: !Ref SupabaseServiceRoleKeySecret
            - Name: SUPABASE_ANON_KEY
              ValueFrom: !Ref SupabaseAnonKeySecret
          LogConfiguration:
            LogDriver: awslogs
            Options:
              awslogs-group: !Ref LogGroup
              awslogs-region: !Ref AWS::Region
              awslogs-stream-prefix: ecs

  SupabaseUrlSecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: vcon-mcp/supabase-url
      SecretString: !Ref SupabaseUrl

  SupabaseServiceRoleKeySecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: vcon-mcp/supabase-service-role-key
      SecretString: !Ref SupabaseServiceRoleKey

  SupabaseAnonKeySecret:
    Type: AWS::SecretsManager::Secret
    Properties:
      Name: vcon-mcp/supabase-anon-key
      SecretString: !Ref SupabaseAnonKey

  SecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: vCon MCP Server Security Group
      VpcId: !Ref VpcId
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3000
          ToPort: 3000
          CidrIp: 0.0.0.0/0

  Service:
    Type: AWS::ECS::Service
    Properties:
      ServiceName: vcon-mcp
      Cluster: !Ref ECSCluster
      TaskDefinition: !Ref TaskDefinition
      DesiredCount: 2
      LaunchType: FARGATE
      NetworkConfiguration:
        AwsvpcConfiguration:
          AssignPublicIp: ENABLED
          Subnets: !Ref SubnetIds
          SecurityGroups:
            - !Ref SecurityGroup

Outputs:
  ClusterArn:
    Value: !GetAtt ECSCluster.Arn
  ServiceName:
    Value: !Ref Service
```

### AWS App Runner

```yaml
# apprunner.yaml
version: 1.0
runtime: docker
build:
  commands:
    build:
      - echo "Using pre-built image"
run:
  runtime-version: 20
  command: node /app/dist/index.js
  network:
    port: 3000
    env: MCP_HTTP_PORT
  env:
    - name: MCP_HTTP_STATELESS
      value: "true"
    - name: MCP_HTTP_HOST
      value: "0.0.0.0"
```

```bash
# Deploy via CLI
aws apprunner create-service \
  --service-name vcon-mcp \
  --source-configuration '{
    "ImageRepository": {
      "ImageIdentifier": "public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main",
      "ImageRepositoryType": "ECR_PUBLIC",
      "ImageConfiguration": {
        "Port": "3000",
        "RuntimeEnvironmentVariables": {
          "MCP_HTTP_STATELESS": "true",
          "SUPABASE_URL": "https://your-project.supabase.co"
        }
      }
    }
  }'
```

***

## Google Cloud Platform

### Cloud Run

```bash
# Deploy to Cloud Run
gcloud run deploy vcon-mcp \
  --image public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main \
  --platform managed \
  --region us-central1 \
  --port 3000 \
  --memory 512Mi \
  --cpu 1 \
  --min-instances 1 \
  --max-instances 10 \
  --set-env-vars "MCP_HTTP_STATELESS=true,MCP_HTTP_HOST=0.0.0.0" \
  --set-secrets "SUPABASE_URL=vcon-supabase-url:latest,SUPABASE_SERVICE_ROLE_KEY=vcon-supabase-key:latest,SUPABASE_ANON_KEY=vcon-supabase-anon-key:latest"
```

#### Cloud Run YAML

```yaml
# service.yaml
apiVersion: serving.knative.dev/v1
kind: Service
metadata:
  name: vcon-mcp
  annotations:
    run.googleapis.com/ingress: all
spec:
  template:
    metadata:
      annotations:
        autoscaling.knative.dev/minScale: '1'
        autoscaling.knative.dev/maxScale: '10'
    spec:
      containerConcurrency: 100
      timeoutSeconds: 300
      containers:
      - image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
        ports:
        - containerPort: 3000
        env:
        - name: MCP_HTTP_STATELESS
          value: "true"
        - name: MCP_HTTP_HOST
          value: "0.0.0.0"
        - name: SUPABASE_URL
          valueFrom:
            secretKeyRef:
              name: vcon-supabase-url
              key: latest
        - name: SUPABASE_SERVICE_ROLE_KEY
          valueFrom:
            secretKeyRef:
              name: vcon-supabase-key
              key: latest
        - name: SUPABASE_ANON_KEY
          valueFrom:
            secretKeyRef:
              name: vcon-supabase-anon-key
              key: latest
        resources:
          limits:
            memory: 512Mi
            cpu: '1'
```

```bash
# Create secrets first
echo -n "https://your-project.supabase.co" | gcloud secrets create vcon-supabase-url --data-file=-
echo -n "your-service-role-key" | gcloud secrets create vcon-supabase-key --data-file=-
echo -n "your-anon-key" | gcloud secrets create vcon-supabase-anon-key --data-file=-

# Deploy
gcloud run services replace service.yaml --region us-central1
```

### Google Kubernetes Engine (GKE)

Use the standard [Kubernetes manifests](/deployment/kubernetes) with GKE-specific annotations:

```yaml
# Add to deployment metadata
annotations:
  cloud.google.com/neg: '{"ingress": true}'
```

***

## Microsoft Azure

### Azure Container Apps

```bash
# Create Container App
az containerapp create \
  --name vcon-mcp \
  --resource-group myResourceGroup \
  --environment myEnvironment \
  --image public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main \
  --target-port 3000 \
  --ingress external \
  --cpu 0.5 \
  --memory 1.0Gi \
  --min-replicas 1 \
  --max-replicas 10 \
  --secrets supabase-url=secretref:supabase-url,supabase-key=secretref:supabase-key,supabase-anon-key=secretref:supabase-anon-key \
  --env-vars \
    MCP_HTTP_STATELESS=true \
    MCP_HTTP_HOST=0.0.0.0 \
    SUPABASE_URL=secretref:supabase-url \
    SUPABASE_SERVICE_ROLE_KEY=secretref:supabase-key \
    SUPABASE_ANON_KEY=secretref:supabase-anon-key
```

#### Bicep Template

```bicep
// main.bicep
param location string = resourceGroup().location
param containerAppName string = 'vcon-mcp'
param supabaseUrl string
@secure()
param supabaseServiceRoleKey string
@secure()
param supabaseAnonKey string

resource containerAppEnvironment 'Microsoft.App/managedEnvironments@2023-05-01' = {
  name: '${containerAppName}-env'
  location: location
  properties: {}
}

resource containerApp 'Microsoft.App/containerApps@2023-05-01' = {
  name: containerAppName
  location: location
  properties: {
    managedEnvironmentId: containerAppEnvironment.id
    configuration: {
      ingress: {
        external: true
        targetPort: 3000
        transport: 'http'
      }
      secrets: [
        {
          name: 'supabase-url'
          value: supabaseUrl
        }
        {
          name: 'supabase-service-role-key'
          value: supabaseServiceRoleKey
        }
        {
          name: 'supabase-anon-key'
          value: supabaseAnonKey
        }
      ]
    }
    template: {
      containers: [
        {
          name: 'vcon-mcp'
          image: 'public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main'
          resources: {
            cpu: json('0.5')
            memory: '1Gi'
          }
          env: [
            {
              name: 'MCP_HTTP_STATELESS'
              value: 'true'
            }
            {
              name: 'MCP_HTTP_HOST'
              value: '0.0.0.0'
            }
            {
              name: 'SUPABASE_URL'
              secretRef: 'supabase-url'
            }
            {
              name: 'SUPABASE_SERVICE_ROLE_KEY'
              secretRef: 'supabase-service-role-key'
            }
            {
              name: 'SUPABASE_ANON_KEY'
              secretRef: 'supabase-anon-key'
            }
          ]
        }
      ]
      scale: {
        minReplicas: 1
        maxReplicas: 10
        rules: [
          {
            name: 'http-scaling'
            http: {
              metadata: {
                concurrentRequests: '100'
              }
            }
          }
        ]
      }
    }
  }
}

output fqdn string = containerApp.properties.configuration.ingress.fqdn
```

### Azure Container Instances (ACI)

```bash
# Quick deployment with ACI
az container create \
  --resource-group myResourceGroup \
  --name vcon-mcp \
  --image public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main \
  --dns-name-label vcon-mcp \
  --ports 3000 \
  --cpu 1 \
  --memory 1 \
  --environment-variables \
    MCP_HTTP_STATELESS=true \
    MCP_HTTP_HOST=0.0.0.0 \
  --secure-environment-variables \
    SUPABASE_URL=https://your-project.supabase.co \
    SUPABASE_SERVICE_ROLE_KEY=your-key \
    SUPABASE_ANON_KEY=your-anon-key
```

***

## DigitalOcean

### App Platform

```yaml
# .do/app.yaml
name: vcon-mcp
services:
- name: vcon-mcp
  image:
    registry_type: DOCKER_HUB
    registry: public.ecr.aws
    repository: r4g1k2s3/vcon-dev/vcon-mcp
    tag: main
  http_port: 3000
  instance_count: 2
  instance_size_slug: basic-xs
  envs:
  - key: MCP_HTTP_STATELESS
    value: "true"
  - key: MCP_HTTP_HOST
    value: "0.0.0.0"
  - key: SUPABASE_URL
    type: SECRET
    value: EV[SUPABASE_URL]
  - key: SUPABASE_SERVICE_ROLE_KEY
    type: SECRET
    value: EV[SUPABASE_SERVICE_ROLE_KEY]
  - key: SUPABASE_ANON_KEY
    type: SECRET
    value: EV[SUPABASE_ANON_KEY]
  health_check:
    http_path: /api/v1/health
    initial_delay_seconds: 10
    period_seconds: 30
```

```bash
doctl apps create --spec .do/app.yaml
```

***

## Fly.io

```toml
# fly.toml
app = "vcon-mcp"
primary_region = "iad"

[build]
  image = "public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main"

[env]
  MCP_HTTP_STATELESS = "true"
  MCP_HTTP_HOST = "0.0.0.0"
  MCP_HTTP_PORT = "8080"

[http_service]
  internal_port = 8080
  force_https = true
  auto_stop_machines = true
  auto_start_machines = true
  min_machines_running = 1

[[vm]]
  cpu_kind = "shared"
  cpus = 1
  memory_mb = 512
```

```bash
# Set secrets
fly secrets set SUPABASE_URL=https://your-project.supabase.co
fly secrets set SUPABASE_SERVICE_ROLE_KEY=your-key
fly secrets set SUPABASE_ANON_KEY=your-anon-key

# Deploy
fly deploy
```

***

## Railway

```json
// railway.json
{
  "$schema": "https://railway.app/railway.schema.json",
  "build": {
    "builder": "DOCKERFILE"
  },
  "deploy": {
    "startCommand": "node /app/dist/index.js",
    "healthcheckPath": "/api/v1/health",
    "healthcheckTimeout": 30,
    "restartPolicyType": "ON_FAILURE"
  }
}
```

Or deploy via CLI:

```bash
railway login
railway init
railway add --docker public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
railway variables set MCP_HTTP_STATELESS=true
railway variables set SUPABASE_URL=https://your-project.supabase.co
railway variables set SUPABASE_SERVICE_ROLE_KEY=your-key
railway variables set SUPABASE_ANON_KEY=your-anon-key
railway up
```

***

## Render

```yaml
# render.yaml
services:
  - type: web
    name: vcon-mcp
    env: docker
    dockerfilePath: ./Dockerfile
    # Or use pre-built image:
    # image:
    #   url: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    plan: starter
    envVars:
      - key: MCP_HTTP_STATELESS
        value: true
      - key: MCP_HTTP_HOST
        value: 0.0.0.0
      - key: SUPABASE_URL
        sync: false
      - key: SUPABASE_SERVICE_ROLE_KEY
        sync: false
      - key: SUPABASE_ANON_KEY
        sync: false
    healthCheckPath: /api/v1/health
```

***

## Comparison Table

| Provider     | Service        | Min Cost         | Auto-scaling | Cold Start |
| ------------ | -------------- | ---------------- | ------------ | ---------- |
| AWS          | ECS Fargate    | \~$30/mo         | Yes          | No         |
| AWS          | App Runner     | \~$5/mo          | Yes          | \~2s       |
| GCP          | Cloud Run      | \~$0 (free tier) | Yes          | \~1s       |
| Azure        | Container Apps | \~$15/mo         | Yes          | \~2s       |
| DigitalOcean | App Platform   | \~$5/mo          | Yes          | No         |
| Fly.io       | Machines       | \~$5/mo          | Yes          | \~1s       |
| Railway      | Container      | \~$5/mo          | Limited      | No         |
| Render       | Web Service    | \~$7/mo          | Limited      | \~30s      |

## Next Steps

* [Kubernetes Deployment](/deployment/kubernetes) - Container orchestration
* [Docker Deployment](/deployment/docker) - Container basics
* [Security](/deployment/security) - Production security hardening


# Self-Hosted Supabase

Deploy vCON MCP with a self-hosted Supabase instance for complete control over your infrastructure.

## Table of Contents

* [Architecture Overview](#architecture-overview)
* [Prerequisites](#prerequisites)
* [1. Create Directory Structure](#1-create-directory-structure)
* [2. Configure Environment Variables](#2-configure-environment-variables)
* [3. Create Supabase Database Files](#3-create-supabase-database-files)
* [4. Create Kong API Gateway Configuration](#4-create-kong-api-gateway-configuration)
* [5. Create Docker Compose File](#5-create-docker-compose-file)
* [6. Start the Stack](#6-start-the-stack)
* [7. Verify Deployment](#7-verify-deployment)
* [8. Pushing vCONs to vCON MCP](#8-pushing-vcons-to-vcon-mcp)
* [9. Configuration Reference](#9-configuration-reference)
* [10. Operations](#10-operations)
* [11. Troubleshooting](#11-troubleshooting)

***

## Architecture Overview

```
┌─────────────────────────────────────────────────────────────────────────────┐
│                              Docker Host                                    │
├─────────────────────────────────────────────────────────────────────────────┤
│                                                                             │
│  External Systems                    vCON MCP Stack                         │
│  ┌────────────────────┐             ┌────────────────────┐                  │
│  │   vCON Ingestion   │────────────▶│     vcon-mcp       │                  │
│  │   Endpoint         │   HTTP      │   Port: 3002       │                  │
│  │                    │   :3002     │                    │                  │
│  └────────────────────┘             └─────────┬──────────┘                  │
│                                               │                             │
│                                               ▼                             │
│                                     ┌────────────────────┐                  │
│                                     │  vcon-supabase-    │                  │
│                                     │  kong (Gateway)    │                  │
│                                     └─────────┬──────────┘                  │
│                                               │                             │
│            ┌──────────────────────────────────┼──────────────────┐          │
│            │                                  │                  │          │
│            ▼                                  ▼                  ▼          │
│  ┌─────────────────┐              ┌─────────────────┐  ┌─────────────────┐  │
│  │  vcon-supabase  │              │  vcon-supabase  │  │  vcon-supabase  │  │
│  │  -auth          │              │  -rest          │  │  -storage       │  │
│  └─────────────────┘              └─────────────────┘  └─────────────────┘  │
│            │                                  │                             │
│            └──────────────────┬───────────────┘                             │
│                               ▼                                             │
│                     ┌─────────────────┐                                     │
│                     │  vcon-supabase  │                                     │
│                     │  -db (Postgres) │                                     │
│                     └─────────────────┘                                     │
│                                                                             │
└─────────────────────────────────────────────────────────────────────────────┘
```

The vCON MCP stack includes:

| Service                   | Description                                  |
| ------------------------- | -------------------------------------------- |
| **vcon-mcp**              | Main application server (HTTP MCP transport) |
| **ofelia**                | Job scheduler for embedding vCONs            |
| **vcon-supabase-db**      | PostgreSQL database                          |
| **vcon-supabase-kong**    | API Gateway                                  |
| **vcon-supabase-auth**    | GoTrue authentication server                 |
| **vcon-supabase-rest**    | PostgREST database REST API                  |
| **vcon-supabase-storage** | File storage API                             |

***

## Prerequisites

* Docker Engine 20.10+ and Docker Compose V2
* At least 4GB RAM available for Docker
* Ports available: `3002` (MCP API) or configurable via Docker Compose port mapping
* Embedding API access (one of the following):
  * Azure OpenAI API
  * OpenAI API
  * Hugging Face API

***

## 1. Create Directory Structure

```bash
mkdir -p ~/vcon-mcp
cd ~/vcon-mcp

# Create volume directories
mkdir -p volumes/{db,api,storage,logs,functions,pooler}
mkdir -p volumes/db/{data,init}
```

***

## 2. Configure Environment Variables

Create `.env` file with your configuration:

```bash
cat > .env << 'EOF'
############
# Secrets
# YOU MUST CHANGE THESE BEFORE GOING INTO PRODUCTION
############

POSTGRES_PASSWORD=your-super-secret-and-long-postgres-password
JWT_SECRET=your-super-secret-jwt-token-with-at-least-32-characters-long
ANON_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJhbm9uIiwKICAgICJpc3MiOiAic3VwYWJhc2UtZGVtbyIsCiAgICAiaWF0IjogMTY0MTc2OTIwMCwKICAgICJleHAiOiAxNzk5NTM1NjAwCn0.dc_X5iR_VP_qT0zsiyj_I_OZ2T9FtRU2BBNWN8Bu4GE
SERVICE_ROLE_KEY=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyAgCiAgICAicm9sZSI6ICJzZXJ2aWNlX3JvbGUiLAogICAgImlzcyI6ICJzdXBhYmFzZS1kZW1vIiwKICAgICJpYXQiOiAxNjQxNzY5MjAwLAogICAgImV4cCI6IDE3OTk1MzU2MDAKfQ.dBOgCXw-qUYQq6dAR0U5uFw1x4L0fNXp1rL2zy7sdBw
DASHBOARD_USERNAME=supabase
DASHBOARD_PASSWORD=this_password_is_insecure_and_should_be_updated

############
# Database - The default values are compatible with Postgres Supabase docker image
############

POSTGRES_HOST=vcon-supabase-db
POSTGRES_DB=postgres
POSTGRES_PORT=5432
# default user is postgres

############
# API Proxy - Configuration for the Kong Reverse proxy.
############

KONG_HTTP_PORT=8443

############
# API - Configuration for PostgREST.
############

PGRST_DB_SCHEMAS=public,storage,graphql_public

############
# Auth - Configuration for the GoTrue authentication server.
############

## General
SITE_URL=http://localhost:3000
ADDITIONAL_REDIRECT_URLS=
JWT_EXPIRY=3600
DISABLE_SIGNUP=false
API_EXTERNAL_URL=http://localhost:8443

## Mailer Config
MAILER_URLPATHS_CONFIRMATION="/auth/v1/verify"
MAILER_URLPATHS_INVITE="/auth/v1/verify"
MAILER_URLPATHS_RECOVERY="/auth/v1/verify"
MAILER_URLPATHS_EMAIL_CHANGE="/auth/v1/verify"

## Email auth
ENABLE_EMAIL_SIGNUP=true
ENABLE_EMAIL_AUTOCONFIRM=true
SMTP_ADMIN_EMAIL=admin@example.com
SMTP_HOST=supabase-mail
SMTP_PORT=2500
SMTP_USER=fake_mail_user
SMTP_PASS=fake_mail_password
SMTP_SENDER_NAME=fake_sender

## Phone auth
ENABLE_PHONE_SIGNUP=false
ENABLE_PHONE_AUTOCONFIRM=true

## Anonymous auth
ENABLE_ANONYMOUS_USERS=false
EOF
```

> **Important**: For production, generate new secrets:
>
> ```bash
> # Generate secure passwords/secrets
> openssl rand -base64 32
> ```

***

## 3. Create Supabase Database Files

### 3.1 Create `volumes/db/roles.sql`

```bash
cat > volumes/db/roles.sql << 'EOF'
-- NOTE: change to your own passwords for production environments
\set pgpass `echo "$POSTGRES_PASSWORD"`

ALTER USER authenticator WITH PASSWORD :'pgpass';
ALTER USER pgbouncer WITH PASSWORD :'pgpass';
ALTER USER supabase_auth_admin WITH PASSWORD :'pgpass';
ALTER USER supabase_functions_admin WITH PASSWORD :'pgpass';
ALTER USER supabase_storage_admin WITH PASSWORD :'pgpass';
EOF
```

### 3.2 Create `volumes/db/jwt.sql`

```bash
cat > volumes/db/jwt.sql << 'EOF'
\set jwt_secret `echo "$JWT_SECRET"`
\set jwt_exp `echo "$JWT_EXP"`

ALTER DATABASE postgres SET "app.settings.jwt_secret" TO :'jwt_secret';
ALTER DATABASE postgres SET "app.settings.jwt_exp" TO :'jwt_exp';
EOF
```

### 3.3 Create `volumes/db/_supabase.sql`

```bash
cat > volumes/db/_supabase.sql << 'EOF'
\set pguser `echo "$POSTGRES_USER"`

CREATE DATABASE _supabase WITH OWNER :pguser;
EOF
```

### 3.4 Create placeholder SQL files

```bash
# These can be minimal for vCON MCP
echo "SELECT 1;" > volumes/db/realtime.sql
echo "SELECT 1;" > volumes/db/webhooks.sql
echo "SELECT 1;" > volumes/db/logs.sql
echo "SELECT 1;" > volumes/db/pooler.sql
```

***

## 4. Create Kong API Gateway Configuration

Create `volumes/api/kong.yml`:

```bash
cat > volumes/api/kong.yml << 'EOF'
_format_version: '2.1'
_transform: true

###
### Consumers / Users
###
consumers:
  - username: DASHBOARD
  - username: anon
    keyauth_credentials:
      - key: $SUPABASE_ANON_KEY
  - username: service_role
    keyauth_credentials:
      - key: $SUPABASE_SERVICE_KEY

###
### Access Control List
###
acls:
  - consumer: anon
    group: anon
  - consumer: service_role
    group: admin

###
### Dashboard credentials
###
basicauth_credentials:
  - consumer: DASHBOARD
    username: $DASHBOARD_USERNAME
    password: $DASHBOARD_PASSWORD

###
### API Routes
###
services:
  ## Open Auth routes
  - name: auth-v1-open
    url: http://vcon-supabase-auth:9999/verify
    routes:
      - name: auth-v1-open
        strip_path: true
        paths:
          - /auth/v1/verify
    plugins:
      - name: cors
  - name: auth-v1-open-callback
    url: http://vcon-supabase-auth:9999/callback
    routes:
      - name: auth-v1-open-callback
        strip_path: true
        paths:
          - /auth/v1/callback
    plugins:
      - name: cors
  - name: auth-v1-open-authorize
    url: http://vcon-supabase-auth:9999/authorize
    routes:
      - name: auth-v1-open-authorize
        strip_path: true
        paths:
          - /auth/v1/authorize
    plugins:
      - name: cors

  ## Secure Auth routes
  - name: auth-v1
    _comment: 'GoTrue: /auth/v1/* -> http://vcon-supabase-auth:9999/*'
    url: http://vcon-supabase-auth:9999/
    routes:
      - name: auth-v1-all
        strip_path: true
        paths:
          - /auth/v1/
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: false
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  ## Secure REST routes
  - name: rest-v1
    _comment: 'PostgREST: /rest/v1/* -> http://vcon-supabase-rest:3000/*'
    url: http://vcon-supabase-rest:3000/
    routes:
      - name: rest-v1-all
        strip_path: true
        paths:
          - /rest/v1/
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: true
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  ## Secure GraphQL routes
  - name: graphql-v1
    _comment: 'PostgREST: /graphql/v1/* -> http://vcon-supabase-rest:3000/rpc/graphql'
    url: http://vcon-supabase-rest:3000/rpc/graphql
    routes:
      - name: graphql-v1-all
        strip_path: true
        paths:
          - /graphql/v1
    plugins:
      - name: cors
      - name: key-auth
        config:
          hide_credentials: true
      - name: request-transformer
        config:
          add:
            headers:
              - Content-Profile:graphql_public
      - name: acl
        config:
          hide_groups_header: true
          allow:
            - admin
            - anon

  ## Storage routes
  - name: storage-v1
    _comment: 'Storage: /storage/v1/* -> http://vcon-supabase-storage:5000/*'
    url: http://vcon-supabase-storage:5000/
    routes:
      - name: storage-v1-all
        strip_path: true
        paths:
          - /storage/v1/
    plugins:
      - name: cors

  ## Health check endpoint
  - name: health
    _comment: 'Health check endpoint'
    url: http://vcon-supabase-auth:9999/health
    routes:
      - name: health-check
        strip_path: true
        paths:
          - /health
    plugins:
      - name: cors
EOF
```

***

## 5. Create Docker Compose File

Create `docker-compose.yml`:

```yaml
# vCON MCP with Self-Hosted Supabase
#
# Usage:
#   Start:    docker compose up -d
#   Stop:     docker compose down
#   Logs:     docker compose logs -f
#   Status:   docker compose ps

name: vcon-mcp

services:

  # ===========================================
  # Ofelia Job Scheduler
  # ===========================================
  ofelia:
    container_name: vcon-mcp-ofelia
    image: mcuadros/ofelia:latest
    restart: unless-stopped
    depends_on:
      vcon-mcp:
        condition: service_healthy
    command: daemon --docker
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

  # ===========================================
  # vCON MCP Server - Main Application
  # ===========================================
  vcon-mcp:
    container_name: vcon-mcp
    image: public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:main
    restart: unless-stopped
    ports:
      - "3002:3000"
    depends_on:
      vcon-supabase-kong:
        condition: service_started
    environment:
      - SUPABASE_URL=http://vcon-supabase-kong:8000
      - SUPABASE_SERVICE_ROLE_KEY=${SERVICE_ROLE_KEY}
      - SUPABASE_ANON_KEY=${ANON_KEY}
      - MCP_HTTP_STATELESS=true
      - MCP_TRANSPORT=http
      - MCP_HTTP_HOST=0.0.0.0
      - MCP_HTTP_PORT=3000
      #
      # Embedding Configuration - Choose ONE provider:
      #
      # Option 1: Azure OpenAI
      - AZURE_OPENAI_EMBEDDING_ENDPOINT=https://your-resource.openai.azure.com
      - AZURE_OPENAI_EMBEDDING_API_VERSION=2023-05-15
      - AZURE_OPENAI_EMBEDDING_API_KEY=your-azure-api-key
      #
      # Option 2: OpenAI (uncomment and configure)
      # - OPENAI_API_KEY=your-openai-api-key
      #
      # Option 3: Hugging Face (uncomment and configure)
      # - HUGGINGFACE_API_KEY=your-huggingface-api-key
      #
      # Tool categories: read, write, schema, analytics, infra
      # Only enable read operations for production deployments
      - MCP_ENABLED_CATEGORIES=read
      - API_KEYS=your-api-key
    labels:
      ofelia.enabled: "true"
      ofelia.job-exec.embed-vcons.schedule: "0 */10 * * *"
      ofelia.job-exec.embed-vcons.command: "/app/docker-entrypoint.sh script embed-vcons --continuous --limit=500"
      ofelia.job-exec.embed-vcons.no-overlap: "true"
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3000/api/v1/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  # ===========================================
  # Supabase Core Services
  # ===========================================

  # PostgreSQL Database
  vcon-supabase-db:
    container_name: vcon-supabase-db
    image: supabase/postgres:15.8.1.085
    restart: unless-stopped
    volumes:
      - ./volumes/db/realtime.sql:/docker-entrypoint-initdb.d/migrations/99-realtime.sql:Z
      - ./volumes/db/webhooks.sql:/docker-entrypoint-initdb.d/init-scripts/98-webhooks.sql:Z
      - ./volumes/db/roles.sql:/docker-entrypoint-initdb.d/init-scripts/99-roles.sql:Z
      - ./volumes/db/jwt.sql:/docker-entrypoint-initdb.d/init-scripts/99-jwt.sql:Z
      - ./volumes/db/data:/var/lib/postgresql/data:Z
      - ./volumes/db/_supabase.sql:/docker-entrypoint-initdb.d/migrations/97-_supabase.sql:Z
      - ./volumes/db/logs.sql:/docker-entrypoint-initdb.d/migrations/99-logs.sql:Z
      - ./volumes/db/pooler.sql:/docker-entrypoint-initdb.d/migrations/99-pooler.sql:Z
      - vcon-db-config:/etc/postgresql-custom
    healthcheck:
      test: ["CMD", "pg_isready", "-U", "postgres", "-h", "localhost"]
      interval: 5s
      timeout: 5s
      retries: 10
    environment:
      POSTGRES_HOST: /var/run/postgresql
      PGPORT: ${POSTGRES_PORT}
      POSTGRES_PORT: ${POSTGRES_PORT}
      PGPASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      PGDATABASE: ${POSTGRES_DB}
      POSTGRES_DB: ${POSTGRES_DB}
      JWT_SECRET: ${JWT_SECRET}
      JWT_EXP: ${JWT_EXPIRY}
    command:
      - postgres
      - -c
      - config_file=/etc/postgresql/postgresql.conf
      - -c
      - log_min_messages=fatal

  # Kong API Gateway
  vcon-supabase-kong:
    container_name: vcon-supabase-kong
    image: kong:2.8.1
    restart: unless-stopped
    ports:
      - "${KONG_HTTP_PORT}:8000/tcp"
    volumes:
      - ./volumes/api/kong.yml:/home/kong/temp.yml:ro,z
    depends_on:
      vcon-supabase-auth:
        condition: service_healthy
    environment:
      KONG_DATABASE: "off"
      KONG_DECLARATIVE_CONFIG: /home/kong/kong.yml
      KONG_DNS_ORDER: LAST,A,CNAME
      KONG_PLUGINS: request-transformer,cors,key-auth,acl,basic-auth,request-termination
      KONG_NGINX_PROXY_PROXY_BUFFER_SIZE: 160k
      KONG_NGINX_PROXY_PROXY_BUFFERS: 64 160k
      SUPABASE_ANON_KEY: ${ANON_KEY}
      SUPABASE_SERVICE_KEY: ${SERVICE_ROLE_KEY}
      DASHBOARD_USERNAME: ${DASHBOARD_USERNAME}
      DASHBOARD_PASSWORD: ${DASHBOARD_PASSWORD}
    entrypoint: bash -c 'eval "echo \"$$(cat ~/temp.yml)\"" > ~/kong.yml && /docker-entrypoint.sh kong docker-start'

  # GoTrue - Authentication Server
  vcon-supabase-auth:
    container_name: vcon-supabase-auth
    image: supabase/gotrue:v2.184.0
    restart: unless-stopped
    depends_on:
      vcon-supabase-db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9999/health"]
      timeout: 5s
      interval: 5s
      retries: 3
    environment:
      GOTRUE_API_HOST: 0.0.0.0
      GOTRUE_API_PORT: 9999
      API_EXTERNAL_URL: ${API_EXTERNAL_URL}

      GOTRUE_DB_DRIVER: postgres
      GOTRUE_DB_DATABASE_URL: postgres://supabase_auth_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}

      GOTRUE_SITE_URL: ${SITE_URL}
      GOTRUE_URI_ALLOW_LIST: ${ADDITIONAL_REDIRECT_URLS}
      GOTRUE_DISABLE_SIGNUP: ${DISABLE_SIGNUP}

      GOTRUE_JWT_ADMIN_ROLES: service_role
      GOTRUE_JWT_AUD: authenticated
      GOTRUE_JWT_DEFAULT_GROUP_NAME: authenticated
      GOTRUE_JWT_EXP: ${JWT_EXPIRY}
      GOTRUE_JWT_SECRET: ${JWT_SECRET}

      GOTRUE_EXTERNAL_EMAIL_ENABLED: ${ENABLE_EMAIL_SIGNUP}
      GOTRUE_EXTERNAL_ANONYMOUS_USERS_ENABLED: ${ENABLE_ANONYMOUS_USERS}
      GOTRUE_MAILER_AUTOCONFIRM: ${ENABLE_EMAIL_AUTOCONFIRM}

      GOTRUE_SMTP_ADMIN_EMAIL: ${SMTP_ADMIN_EMAIL}
      GOTRUE_SMTP_HOST: ${SMTP_HOST}
      GOTRUE_SMTP_PORT: ${SMTP_PORT}
      GOTRUE_SMTP_USER: ${SMTP_USER}
      GOTRUE_SMTP_PASS: ${SMTP_PASS}
      GOTRUE_SMTP_SENDER_NAME: ${SMTP_SENDER_NAME}
      GOTRUE_MAILER_URLPATHS_INVITE: ${MAILER_URLPATHS_INVITE}
      GOTRUE_MAILER_URLPATHS_CONFIRMATION: ${MAILER_URLPATHS_CONFIRMATION}
      GOTRUE_MAILER_URLPATHS_RECOVERY: ${MAILER_URLPATHS_RECOVERY}
      GOTRUE_MAILER_URLPATHS_EMAIL_CHANGE: ${MAILER_URLPATHS_EMAIL_CHANGE}

      GOTRUE_EXTERNAL_PHONE_ENABLED: ${ENABLE_PHONE_SIGNUP}
      GOTRUE_SMS_AUTOCONFIRM: ${ENABLE_PHONE_AUTOCONFIRM}

  # PostgREST - Database REST API
  vcon-supabase-rest:
    container_name: vcon-supabase-rest
    image: postgrest/postgrest:v14.1
    restart: unless-stopped
    depends_on:
      vcon-supabase-db:
        condition: service_healthy
    environment:
      PGRST_DB_URI: postgres://authenticator:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
      PGRST_DB_SCHEMAS: ${PGRST_DB_SCHEMAS}
      PGRST_DB_ANON_ROLE: anon
      PGRST_JWT_SECRET: ${JWT_SECRET}
      PGRST_DB_USE_LEGACY_GUCS: "false"
      PGRST_APP_SETTINGS_JWT_SECRET: ${JWT_SECRET}
      PGRST_APP_SETTINGS_JWT_EXP: ${JWT_EXPIRY}
    command: ["postgrest"]

  # Storage API
  vcon-supabase-storage:
    container_name: vcon-supabase-storage
    image: supabase/storage-api:v1.33.0
    restart: unless-stopped
    volumes:
      - ./volumes/storage:/var/lib/storage:z
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:5000/status"]
      timeout: 5s
      interval: 5s
      retries: 3
    depends_on:
      vcon-supabase-db:
        condition: service_healthy
      vcon-supabase-rest:
        condition: service_started
    environment:
      ANON_KEY: ${ANON_KEY}
      SERVICE_KEY: ${SERVICE_ROLE_KEY}
      POSTGREST_URL: http://vcon-supabase-rest:3000
      PGRST_JWT_SECRET: ${JWT_SECRET}
      DATABASE_URL: postgres://supabase_storage_admin:${POSTGRES_PASSWORD}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}
      REQUEST_ALLOW_X_FORWARDED_PATH: "true"
      FILE_SIZE_LIMIT: 52428800
      STORAGE_BACKEND: file
      FILE_STORAGE_BACKEND_PATH: /var/lib/storage
      TENANT_ID: stub
      REGION: stub
      GLOBAL_S3_BUCKET: stub
      ENABLE_IMAGE_TRANSFORMATION: "false"

volumes:
  vcon-db-config:
```

***

## 6. Start the Stack

```bash
cd ~/vcon-mcp
docker compose up -d
```

Watch the startup logs:

```bash
docker compose logs -f
```

Wait until all services are healthy (typically 1-2 minutes for first startup).

***

## 7. Verify Deployment

### 7.1 Check Service Status

```bash
docker compose ps
```

All services should show as "healthy" or "running".

### 7.2 Test Health Endpoint

```bash
curl http://localhost:3002/api/v1/health
```

Expected response:

```json
{"status":"ok"}
```

### 7.3 View Logs

```bash
# All services
docker compose logs -f

# Specific service
docker compose logs -f vcon-mcp
```

***

## 8. Pushing vCONs to vCON MCP

vCON MCP exposes an HTTP API for ingesting vCONs. External systems can push vCONs to the endpoint.

### 8.1 API Endpoint

```
POST http://<docker-host>:3002/api/v1/vcons
```

Replace `<docker-host>` with:

* `localhost` if calling from the same machine
* The machine's IP address or hostname if calling from another system

### 8.2 Example: Push a vCON

```bash
curl -X POST http://localhost:3002/api/v1/vcons \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer your-vcon-api-key" \
  -d '{
    "vcon": "0.0.1",
    "uuid": "unique-vcon-id",
    "created_at": "2024-01-15T10:30:00Z",
    "parties": [...],
    "dialog": [...],
    "analysis": [...],
    "attachments": [...]
  }'
```

### 8.3 Webhook Integration

If your vCON ingestion system supports webhooks, configure it to POST vCONs to:

```
http://<docker-host>:3002/api/v1/vcons
```

#### Conserver Integration

For real-time vCON ingestion from [Conserver](https://github.com/vcon-dev/vcon-server), use the `links.webhook` module to push vCONs directly to vCON MCP.

**Example Conserver Configuration:**

```yaml
# conserver.yml
links:
  push_to_vcon_mcp:
    module: links.webhook
    options:
      webhook-urls:
        - http://vcon-mcp:3000/api/v1/vcons

chains:
  call_processing_chain:
    enabled: 1
    ingress_lists:
      - call_ingress
    links:
      - transcribe_openai
      - diarize
      - summarize
      - push_to_vcon_mcp
    storages:
      - postgres
      - elasticsearch
```

**Configuration Notes:**

* The `push_to_vcon_mcp` link uses `links.webhook` to POST vCONs to the MCP endpoint
* Place the webhook link at the end of the chain to push fully processed vCONs (with transcription, diarization, summaries, etc.)

***

## 9. Configuration Reference

### 9.1 Environment Variables

| Variable                    | Description                       | Example                          |
| --------------------------- | --------------------------------- | -------------------------------- |
| `SUPABASE_URL`              | Internal URL to Kong gateway      | `http://vcon-supabase-kong:8000` |
| `SUPABASE_SERVICE_ROLE_KEY` | Service role JWT for admin access | Generated JWT                    |
| `SUPABASE_ANON_KEY`         | Anonymous user JWT                | Generated JWT                    |
| `MCP_ENABLED_CATEGORIES`    | Enabled tool categories           | `read` (for production)          |
| `API_KEYS`                  | API keys for authentication       | Comma-separated keys             |

### 9.2 Embedding Provider Configuration

Choose one of the following embedding providers:

#### Azure OpenAI

```yaml
environment:
  - AZURE_OPENAI_EMBEDDING_ENDPOINT=https://your-resource.openai.azure.com
  - AZURE_OPENAI_EMBEDDING_API_VERSION=2023-05-15
  - AZURE_OPENAI_EMBEDDING_API_KEY=your-api-key
```

#### OpenAI

```yaml
environment:
  - OPENAI_API_KEY=your-openai-api-key
```

#### Hugging Face

```yaml
environment:
  - HUGGINGFACE_API_KEY=your-huggingface-api-key
```

### 9.3 MCP Tool Categories

| Category    | Description                    | Production Use   |
| ----------- | ------------------------------ | ---------------- |
| `read`      | Query vCONs, search, analytics | ✅ Recommended    |
| `write`     | Create/update vCONs            | Use with caution |
| `schema`    | Modify database schema         | Not recommended  |
| `analytics` | Heavy analytics operations     | Use with caution |
| `infra`     | Infrastructure management      | Not recommended  |

### 9.4 Ofelia Job Scheduler

The embedding job runs every 10 minutes to generate embeddings for new vCONs:

```yaml
labels:
  ofelia.enabled: "true"
  ofelia.job-exec.embed-vcons.schedule: "0 */10 * * *"
  ofelia.job-exec.embed-vcons.command: "/app/docker-entrypoint.sh script embed-vcons --continuous --limit=500"
  ofelia.job-exec.embed-vcons.no-overlap: "true"
```

***

## 10. Operations

### 10.1 Common Commands

```bash
# Start services
docker compose up -d

# Stop services
docker compose down

# View logs
docker compose logs -f
docker compose logs -f vcon-mcp

# Restart a specific service
docker compose restart vcon-mcp

# Check service status
docker compose ps

# Execute command in container
docker compose exec vcon-mcp /app/docker-entrypoint.sh script embed-vcons --limit=100
```

### 10.2 Database Backup

```bash
# Create backup
docker compose exec vcon-supabase-db pg_dump -U postgres postgres > backup-$(date +%Y%m%d).sql

# Restore backup
cat backup.sql | docker compose exec -T vcon-supabase-db psql -U postgres postgres
```

### 10.3 Updating Images

```bash
docker compose pull
docker compose up -d
```

### 10.4 Viewing Database

```bash
# Connect to PostgreSQL
docker compose exec vcon-supabase-db psql -U postgres

# List tables
\dt

# Query vCONs
SELECT uuid, created_at FROM vcons LIMIT 10;
```

***

## 11. Troubleshooting

### 11.1 Services Won't Start

**Check port conflicts:**

```bash
sudo netstat -tulpn | grep -E '3002|8443'
# or
sudo lsof -i :3002
```

**Check Docker resources:**

```bash
docker system df
docker stats --no-stream
```

### 11.2 Database Connection Issues

**Check database is healthy:**

```bash
docker compose logs vcon-supabase-db
docker compose exec vcon-supabase-db pg_isready -U postgres
```

**Reset database (WARNING: destroys all data):**

```bash
docker compose down -v
rm -rf volumes/db/data/*
docker compose up -d
```

### 11.3 Kong Gateway Issues

**Check Kong logs:**

```bash
docker compose logs vcon-supabase-kong
```

**Verify Kong config:**

```bash
docker compose exec vcon-supabase-kong kong config parse /home/kong/kong.yml
```

### 11.4 vCON MCP Health Check Fails

**Check application logs:**

```bash
docker compose logs vcon-mcp
```

**Verify Supabase connection:**

```bash
docker compose exec vcon-mcp wget -qO- http://vcon-supabase-kong:8000/health
```

### 11.5 Embedding Job Not Running

**Check Ofelia logs:**

```bash
docker compose logs ofelia
```

**Run embedding manually:**

```bash
docker compose exec vcon-mcp /app/docker-entrypoint.sh script embed-vcons --limit=100
```

***

## Next Steps

* Review [Security Best Practices](/deployment/security) for production hardening
* Set up [Performance Monitoring](/deployment/performance)
* Configure [Kubernetes Deployment](/deployment/kubernetes) for high availability
* Explore [Cloud Provider Options](/deployment/cloud) for managed infrastructure


# Quick Start Guide

**Audience:** Reseller sales engineers and pre-sales staff who need a working demo on a laptop in under 20 minutes.

> VCONIC MCP Server is the reseller distribution of the open-source [`vcon-mcp`](https://github.com/vcon-dev/vcon-mcp) project. All install artifacts ship under the `vcon-mcp` name (npm package, Docker image, REST API path). VCONIC branding applies to packaging, support, and partner tooling — it is not a fork.

## Reseller lens

Use this guide to stand up a single-tenant demo from your laptop. For multi-customer / production patterns, jump straight to the [Installation Guide](/vconic-for-resellers/02-installation-guide).

## What you need

* Docker 24+
* A Supabase project (cloud or [self-hosted](/deployment/self-hosted-supabase))
* An MCP-capable AI client (Claude Desktop is the easiest demo)

## 1. Pull the image

```bash
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:latest
```

Tags published per build: `main-<7-char-sha>`, `latest` (main HEAD), and semver tags (e.g. `1.2.0`, `1.2`, `1`) on tagged releases.

## 2. Apply database migrations

Run migrations against the Supabase project once. The image bundles the Supabase CLI:

```bash
docker run --rm \
  -e SUPABASE_DB_URL='postgresql://postgres:<pwd>@<host>:5432/postgres' \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:latest \
  migrate
```

For deeper context on migrations and what they touch, see [Migration Guide](/reference/migration_guide).

## 3. Start the server (stdio for Claude Desktop)

The fastest demo path is stdio, launched directly by Claude Desktop. Add this block to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):

```json
{
  "mcpServers": {
    "vconic": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-e", "SUPABASE_URL=https://your-project.supabase.co",
        "-e", "SUPABASE_ANON_KEY=your-anon-key",
        "public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:latest"
      ]
    }
  }
}
```

Restart Claude Desktop. The `vconic` server appears in the MCP tools menu.

## 4. Smoke-test from the client

Ask the assistant something simple:

> "Show me the database shape."

It should call `get_database_shape` and return tables and row counts.

## 5. Next steps

* Production install → [Installation Guide](/vconic-for-resellers/02-installation-guide)
* Tune env vars → [Configuration Guide](/vconic-for-resellers/03-configuration-guide)
* See available tools → [MCP Tools reference](/api-reference/tools)

## See also

* [Quick Start (developer view)](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/quick-start.md)
* [Getting Started](/guide/getting-started)
* [Docker deployment](/deployment/docker)


# Installation Guide

**Audience:** Reseller deployment leads provisioning VCONIC for a single customer environment.

## Reseller lens

A customer install is one VCONIC instance per Supabase project (or per-tenant if running multi-tenant — see [RLS Multi-Tenant](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/rls-multi-tenant.md)). Plan one Docker host per environment (staging, production). Don't share Supabase projects across customers unless RLS is explicitly enabled and verified.

## Prerequisites

| Component                              | Minimum                                                    |
| -------------------------------------- | ---------------------------------------------------------- |
| Docker Engine                          | 24.0+                                                      |
| PostgreSQL (via Supabase)              | 14+                                                        |
| Node.js (only for source/dev installs) | 20+                                                        |
| Outbound HTTPS                         | to Supabase project URL, ECR Public, and (optional) OpenAI |

Optional but commonly needed:

* Reverse proxy with TLS termination (nginx, Caddy, Traefik) for HTTP transport
* Redis for response caching
* OpenAI or LiteLLM credentials for semantic search embeddings

## Install methods

### A. Docker (recommended for customer environments)

```bash
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:1.2.0
```

Pin to a semver tag (`1.2.0`) in customer environments — don't use `latest` in production. Tag policy:

* `main-<sha>` — every push to main
* `latest` — main HEAD (dev / demo only)
* `1.2.0`, `1.2`, `1` — published on git tag releases

See [Docker deployment](/deployment/docker) for image internals (non-root user, dumb-init entrypoint, Supabase CLI bundled).

### B. npm package (for embedded use inside a Node service)

```bash
npm install vcon-mcp
```

The package exposes the server module and types. Suitable when wrapping the server inside another Node application. See [Installation](/guide/installation) for the full developer path.

### C. Source build (for customer-managed forks)

```bash
git clone https://github.com/vcon-dev/vcon-mcp.git
cd vcon-mcp && npm install && npm run build
```

## Step-by-step

1. **Create the Supabase project.** Cloud or [self-hosted](/deployment/self-hosted-supabase).
2. **Apply migrations.** From the Docker image:

   ```bash
   docker run --rm \
     -e SUPABASE_DB_URL='postgresql://...' \
     public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:1.2.0 \
     migrate
   ```
3. **Choose a transport.** See the table below.
4. **Set required env vars.** Minimum: `SUPABASE_URL`, `SUPABASE_ANON_KEY`. See [Configuration Guide](/vconic-for-resellers/03-configuration-guide) for the full list.
5. **Start the container.** Example for HTTP transport:

   ```bash
   docker run -d --name vconic \
     -p 3000:3000 \
     -e SUPABASE_URL='https://...' \
     -e SUPABASE_ANON_KEY='...' \
     -e MCP_TRANSPORT=http \
     -e MCP_HTTP_HOST=0.0.0.0 \
     -e API_KEYS='customer-key-1' \
     -e API_KEYS_READONLY='partner-readonly-key-1' \
     public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:1.2.0
   ```
6. **Verify.** `curl http://localhost:3000/api/v1/health` returns `{"status":"ok"}` with `X-Version` and `X-Git-Commit` response headers.

`API_KEYS` grants full read/write/delete. Hand external consumers a key from `API_KEYS_READONLY` instead: those keys get `403` on every non-GET REST request and cannot call write MCP tools. See [Configuration Guide → Authentication](/vconic-for-resellers/03-configuration-guide#authentication).

### Transport choice

| Transport | When to use                                              | How to launch                                  |
| --------- | -------------------------------------------------------- | ---------------------------------------------- |
| `stdio`   | AI client (Claude Desktop) spawns the server per-session | Default; `MCP_TRANSPORT=stdio` (or unset)      |
| `http`    | Shared deployment, multiple clients, REST API needed     | `MCP_TRANSPORT=http` + `MCP_HTTP_HOST=0.0.0.0` |

## TLS / reverse proxy

VCONIC does not terminate TLS itself. Front it with a reverse proxy. Minimal nginx for HTTP transport:

```nginx
location / {
  proxy_pass http://vconic-host:3000;
  proxy_set_header Host $host;
  proxy_set_header Authorization $http_authorization;
}
```

## Verification checklist

* [ ] `GET /api/v1/health` returns 200
* [ ] `X-Version` response header matches the deployed tag
* [ ] An authenticated MCP request (`tools/list`) returns the expected tool catalog
* [ ] `get_database_shape` reports all migration tables present

## See also

* [Installation (developer view)](/guide/installation)
* [Docker deployment](/deployment/docker)
* [Production setup](/deployment/production)
* [Self-hosted Supabase](/deployment/self-hosted-supabase)


# Configuration Guide

**Audience:** Reseller deployment leads and support engineers configuring VCONIC for a customer environment.

## Reseller lens

VCONIC is configured entirely via environment variables. Every variable documented here exists in [`.env.example`](https://github.com/vcon-dev/vcon-mcp/blob/main/.env.example) on `main` — no invented flags. Treat that file as the source of truth and this guide as the reseller-lens grouping with one-line meanings.

## Database

| Variable                    | Required | Default    | Meaning                                    |
| --------------------------- | -------- | ---------- | ------------------------------------------ |
| `SUPABASE_URL`              | yes      | —          | Supabase project URL                       |
| `SUPABASE_ANON_KEY`         | yes      | —          | Anon key from project API settings         |
| `SUPABASE_SERVICE_ROLE_KEY` | no       | —          | Service role (use sparingly; bypasses RLS) |
| `DB_TYPE`                   | no       | `supabase` | Backend: `supabase` or `mongodb`           |
| `MONGO_URL`                 | no       | —          | Only when `DB_TYPE=mongodb`                |
| `MONGO_DB_NAME`             | no       | `vcon`     | Only when `DB_TYPE=mongodb`                |

## MCP transport

| Variable                   | Default     | Meaning                                |
| -------------------------- | ----------- | -------------------------------------- |
| `MCP_TRANSPORT`            | `stdio`     | `stdio` or `http`                      |
| `MCP_HTTP_HOST`            | `127.0.0.1` | Use `0.0.0.0` in containers            |
| `MCP_HTTP_PORT`            | `3000`      |                                        |
| `MCP_HTTP_STATELESS`       | `false`     | Set `true` to disable session tracking |
| `MCP_HTTP_JSON_ONLY`       | `false`     | Set `true` to disable SSE streaming    |
| `MCP_HTTP_CORS`            | `false`     | Enable CORS for browser clients        |
| `MCP_HTTP_CORS_ORIGIN`     | `*`         | Allowed origin                         |
| `MCP_HTTP_DNS_PROTECTION`  | `false`     | DNS rebinding protection               |
| `MCP_HTTP_ALLOWED_HOSTS`   | —           | Comma-separated whitelist              |
| `MCP_HTTP_ALLOWED_ORIGINS` | —           | Comma-separated whitelist              |

## REST API (HTTP transport only)

| Variable             | Default   | Meaning                             |
| -------------------- | --------- | ----------------------------------- |
| `REST_API_ENABLED`   | `true`    | Enable REST endpoints alongside MCP |
| `REST_API_BASE_PATH` | `/api/v1` | Endpoint prefix                     |
| `CORS_ORIGIN`        | `*`       | REST API CORS                       |

## Authentication

API key auth covers both REST and MCP HTTP endpoints.

| Variable            | Default         | Meaning                                                                  |
| ------------------- | --------------- | ------------------------------------------------------------------------ |
| `API_AUTH_REQUIRED` | `true`          | Require auth on REST + MCP HTTP                                          |
| `API_KEYS`          | —               | Comma-separated keys with full read/write/delete access                  |
| `API_KEYS_READONLY` | —               | Comma-separated read-only keys (GET-only on REST, no write tools on MCP) |
| `API_KEY_HEADER`    | `authorization` | Header to read key from                                                  |

Default header `authorization` accepts `Authorization: Bearer <key>`. Set `API_KEY_HEADER=x-api-key` to use a plain custom header.

**Misconfiguration trap:** `API_AUTH_REQUIRED=true` with no keys in either variable returns `503 Service Unavailable` until a key is set.

**Read-only keys.** Give external consumers an `API_KEYS_READONLY` key. Those keys get `403 Forbidden` on any non-GET REST request and cannot call `write` category MCP tools. `API_KEYS` keys can delete the entire corpus, so never hand one out. A key in both variables is read-only. Details: [Configuration → API Keys and Read-Only Access](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/configuration.md#api-keys-and-read-only-access).

## Multi-tenant (RLS)

| Variable                 | Default  | Meaning                                           |
| ------------------------ | -------- | ------------------------------------------------- |
| `RLS_ENABLED`            | `false`  | Enable Row-Level Security policies                |
| `RLS_DEBUG`              | `false`  | Log RLS decisions (verbose)                       |
| `CURRENT_TENANT_ID`      | —        | Tenant ID applied to service-role queries         |
| `TENANT_ATTACHMENT_TYPE` | `tenant` | Attachment type extracted as tenant marker        |
| `TENANT_JSON_PATH`       | `id`     | Dot-path inside attachment body for the tenant id |

Deep dive: [RLS Multi-Tenant](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/rls-multi-tenant.md).

## Tool surface

Restrict the tool catalog exposed to clients.

| Variable                  | Default | Meaning                                                         |
| ------------------------- | ------- | --------------------------------------------------------------- |
| `MCP_TOOLS_PROFILE`       | `full`  | One of `full`, `readonly`, `user`, `admin`, `minimal`, `public` |
| `MCP_ENABLED_CATEGORIES`  | —       | Comma-separated: e.g. `read,write`                              |
| `MCP_DISABLED_CATEGORIES` | —       | Comma-separated: e.g. `analytics`                               |
| `MCP_DISABLED_TOOLS`      | —       | Specific tool names: e.g. `delete_vcon`                         |

## Embeddings

Semantic and hybrid search require an embeddings provider.

| Variable             | Required          | Meaning                                      |
| -------------------- | ----------------- | -------------------------------------------- |
| `OPENAI_API_KEY`     | for OpenAI direct | Key for embedding generation                 |
| `LITELLM_PROXY_URL`  | for LiteLLM       | Proxy endpoint, e.g. `http://localhost:4000` |
| `LITELLM_MASTER_KEY` | for LiteLLM       | LiteLLM master key                           |

If neither is set, content search and tag search still work; semantic search returns no results.

## Caching

| Variable            | Default | Meaning                       |
| ------------------- | ------- | ----------------------------- |
| `REDIS_URL`         | —       | e.g. `redis://localhost:6379` |
| `VCON_REDIS_EXPIRY` | `3600`  | TTL in seconds                |

## Plugins

The plugin loader accepts module paths. The license variables apply only to plugins that opt in to license-key gating; the core server runs without them.

| Variable            | Default | Meaning                      |
| ------------------- | ------- | ---------------------------- |
| `VCON_PLUGINS_PATH` | —       | Comma-separated module paths |
| `VCON_LICENSE_KEY`  | —       | Optional, plugin-defined     |
| `VCON_OFFLINE_MODE` | `false` | Optional, plugin-defined     |

Architecture: [Plugin reference](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/reference/plugin-architecture.md), [Plugin development](/development/plugins).

## Observability

| Variable             | Default                 | Meaning                          |
| -------------------- | ----------------------- | -------------------------------- |
| `OTEL_ENABLED`       | `true`                  | Enable OpenTelemetry             |
| `OTEL_EXPORTER_TYPE` | `console`               | `console` (no-op) or `otlp`      |
| `OTEL_ENDPOINT`      | `http://localhost:4318` | OTLP collector                   |
| `OTEL_SERVICE_NAME`  | `vcon-mcp-server`       | Span service name                |
| `LOG_LEVEL`          | `info`                  | Pino log level                   |
| `MCP_DEBUG`          | `false`                 | MCP protocol-level debug logging |

Deep dive: [Observability](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/observability.md).

## Worked scenarios

### Claude Desktop (stdio)

Minimum env: `SUPABASE_URL`, `SUPABASE_ANON_KEY`. Everything else default.

### Shared HTTP deployment

```
MCP_TRANSPORT=http
MCP_HTTP_HOST=0.0.0.0
API_AUTH_REQUIRED=true
API_KEYS=key-a,key-b
OPENAI_API_KEY=sk-...
REDIS_URL=redis://redis:6379
```

### Read-only analytics user

```
MCP_TOOLS_PROFILE=readonly
API_KEYS=analytics-only-key
```

## See also

* [Configuration (developer view)](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/configuration.md)
* [RLS Multi-Tenant](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/rls-multi-tenant.md)
* [Plugin architecture](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/reference/plugin-architecture.md)
* [Observability](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/guide/observability.md)


# Administration Guide

**Audience:** Reseller support engineers running day-2 ops on a deployed VCONIC instance.

## Reseller lens

Treat each customer instance as independently operated. Most administration touches three surfaces: the running container, the Supabase database, and the customer's MCP/REST clients.

## Health & version

```bash
curl -s http://<host>:3000/api/v1/health
```

Response headers carry deployment provenance:

* `X-Version` — package version baked into the image
* `X-Git-Commit` — short SHA of the commit
* `X-Build-Time` — image build timestamp

Use these when escalating issues — they identify the exact build.

## Service control

```bash
# Status
docker ps --filter name=vconic

# Logs (Pino JSON, stderr)
docker logs -f vconic | jq 'select(.level >= 40)'

# Graceful restart
docker restart vconic
```

The container uses `dumb-init` as PID 1, so signals propagate cleanly.

## Running migrations

After upgrading the image, run migrations once before restarting the running container. See [Upgrade Guide](/vconic-for-resellers/06-upgrade-guide) for the full procedure. The migration entrypoint:

```bash
docker run --rm \
  -e SUPABASE_DB_URL='postgresql://...' \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:<new-tag> \
  migrate
```

## API key rotation

1. Add the new key to the comma-separated `API_KEYS` env var alongside the old one.
2. Restart the container (both keys are now valid).
3. Update clients to the new key.
4. Remove the old key from `API_KEYS` and restart again.

This is a zero-downtime path because both keys accept traffic during the client cutover.

## Logs

Pino emits structured JSON to stderr. Useful fields:

| Field            | Meaning                                |
| ---------------- | -------------------------------------- |
| `level`          | 30=info, 40=warn, 50=error             |
| `component`      | Originating subsystem                  |
| `service`        | Always `vcon-mcp-server`               |
| `error_code`     | Stable error identifier (when present) |
| `remote_address` | Client IP (HTTP transport)             |
| `duration_ms`    | Operation duration                     |
| `user_agent`     | Client user-agent (HTTP transport)     |

Filter in production with `jq` or your log aggregator. Set `LOG_LEVEL=debug` temporarily to capture more detail.

## Capacity & database health

Use the built-in MCP tools rather than ad-hoc SQL:

| Tool                          | What it tells you                        |
| ----------------------------- | ---------------------------------------- |
| `get_database_shape`          | Tables, indexes, row counts              |
| `get_database_size_info`      | Total size, growth pressure              |
| `get_database_stats`          | Query stats, cache hit ratio             |
| `get_database_analytics`      | Content distribution, ingestion patterns |
| `get_database_health_metrics` | Performance signals + recommendations    |

See [Database tools](/guide/database-tools) for parameter details.

## Backup & restore

Backups are a Supabase responsibility, not VCONIC's. Use:

* Supabase managed backups (cloud) — daily snapshots in the dashboard
* `pg_dump` / `pg_restore` (self-hosted) — point-in-time snapshots

Always snapshot **before** running migrations on a customer environment.

## Embedding refresh

When semantic search misses a vCon, embeddings may be stale or missing. Backfill from a controlled host (not from the production container):

```bash
git clone --depth 1 https://github.com/vcon-dev/vcon-mcp.git
cd vcon-mcp && npm install
npm run sync:embeddings
```

`npm run embeddings:check` reports coverage gaps without writing.

## Tenant troubleshooting (RLS deployments)

When a tenant reports empty results, check tenant context first:

* Confirm the tenant id is reaching the request (header or service-role env).
* Use [Debugging RLS](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/debugging-tenant-rls.md) for the full step-by-step.

## Graceful shutdown

```bash
docker stop --time 30 vconic
```

The 30s grace lets in-flight MCP requests complete.

## See also

* [Database tools](/guide/database-tools)
* [Migration Guide](/reference/migration_guide)
* [Observability](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/observability.md)
* [Debugging Tenant RLS](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/debugging-tenant-rls.md)


# Troubleshooting Guide

**Audience:** Reseller support engineers triaging issues at a customer site before escalating.

## Reseller lens

Run these checks first; they resolve the majority of customer reports without engineering escalation. Each row points at the deeper doc for follow-up.

## First-five checks

1. **Service up?** `docker ps --filter name=vconic`
2. **Health OK?** `curl http://<host>:3000/api/v1/health`
3. **Version known?** `curl -I http://<host>:3000/api/v1/health` → record `X-Version` + `X-Git-Commit`
4. **DB reachable?** Logs show no Supabase connection errors on startup
5. **Auth working?** A request with a valid `API_KEYS` entry returns 200

## Symptom triage

| Symptom                                                        | Likely cause                                                         | First action                                                                                                  |
| -------------------------------------------------------------- | -------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| Container exits immediately                                    | Missing `SUPABASE_URL` or `SUPABASE_ANON_KEY`                        | `docker logs vconic` and check env vars                                                                       |
| 503 on every REST call                                         | `API_AUTH_REQUIRED=true` with empty `API_KEYS`                       | Set `API_KEYS` or `API_AUTH_REQUIRED=false`                                                                   |
| 401 from authenticated client                                  | Wrong `API_KEY_HEADER` or missing `Bearer` prefix                    | Confirm client uses `Authorization: Bearer <key>` (default)                                                   |
| MCP tools menu is empty                                        | `MCP_TOOLS_PROFILE` too restrictive or `MCP_DISABLED_CATEGORIES` set | Remove overrides, restart, retry                                                                              |
| `tools/list` works but `search_vcons_semantic` returns nothing | No `OPENAI_API_KEY` or embeddings not backfilled                     | Set the key; run `npm run sync:embeddings`                                                                    |
| Empty results in `search_vcons` for tenant user                | RLS misconfigured or tenant id missing                               | See [Debugging Tenant RLS](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/debugging-tenant-rls.md) |
| `search_vcons_content` very slow on first call                 | Cold full-text index, expected behavior on large corpora             | Allow up to 120s steady-state; cache warms after first run                                                    |
| `add_attachment` rejects `encoding: "json"`                    | Known quirk of older Python client; not a server bug                 | See [vCon spec corrections](/reference/corrected_schema)                                                      |
| `analysis.schema_version` rejected                             | Spec field is `schema`, not `schema_version`                         | Fix client payload                                                                                            |
| Migrations fail mid-run                                        | Missing `SUPABASE_DB_URL` permission or running against wrong DB     | Verify URL; back up before retry                                                                              |
| pgvector missing                                               | Self-hosted Supabase without the extension installed                 | Enable `vector` extension in the database                                                                     |

## Diagnostic commands

```bash
# Container state and resource use
docker stats --no-stream vconic

# Recent error-level logs
docker logs --since 1h vconic 2>&1 | grep '"level":50' | tail -20

# Effective env (mask secrets before sharing)
docker exec vconic env | grep -E '^(MCP_|SUPABASE_|API_|RLS_|OTEL_)' | sed 's/=.*KEY.*/=***/'

# Health + version headers
curl -s -D - http://localhost:3000/api/v1/health | head -10
```

## Escalation checklist

When opening an internal escalation, include:

* `X-Version` and `X-Git-Commit` from the health endpoint
* Last 200 lines of error-level logs (`level >= 40`)
* Output of `get_database_shape` from an MCP client
* Customer's transport mode (`stdio` vs `http`) and whether RLS is on
* Whether the issue started after a recent upgrade or env change

## See also

* [Troubleshooting (developer view)](/guide/troubleshooting)
* [FAQ](/guide/faq)
* [Debugging Tenant RLS](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/debugging-tenant-rls.md)
* [Spec corrections](/reference/corrected_schema)


# Upgrade Guide

**Audience:** Reseller deployment leads upgrading a customer instance to a newer VCONIC release.

## Reseller lens

Use a stop-the-world upgrade: snapshot, migrate, swap, verify. The procedure is short because each step is non-negotiable.

## Before you start

1. Read the [Release Notes](/vconic-for-resellers/07-release-notes) for the target version.
2. Note breaking changes and new required env vars.
3. **Snapshot the database.** Supabase backup (cloud) or `pg_dump` (self-hosted).
4. Record the current version: `curl -I http://<host>:3000/api/v1/health` — capture `X-Version` and `X-Git-Commit`.

## Upgrade procedure

```bash
# 1. Pull the target image (always pin to a semver tag)
docker pull public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:<new-tag>

# 2. Run new migrations BEFORE swapping the running container
docker run --rm \
  -e SUPABASE_DB_URL='postgresql://...' \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:<new-tag> \
  migrate

# 3. Stop the current container
docker stop --time 30 vconic && docker rm vconic

# 4. Start the new image with the same env file
docker run -d --name vconic \
  --env-file /etc/vconic/env \
  -p 3000:3000 \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:<new-tag>

# 5. Smoke-test
curl -I http://localhost:3000/api/v1/health
# Confirm X-Version matches <new-tag>
```

## Smoke-test (do every time)

* `GET /api/v1/health` → 200, `X-Version` matches target
* One `tools/list` MCP call → expected tool catalog
* One `get_vcon` against a known UUID → returns the vCon
* One `search_vcons` with a known filter → returns expected count

If any check fails, roll back immediately (see below) before investigating.

## Rollback

```bash
# 1. Stop the new container
docker stop vconic && docker rm vconic

# 2. Restart the previous image
docker run -d --name vconic \
  --env-file /etc/vconic/env \
  -p 3000:3000 \
  public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp:<previous-tag>
```

**Database rollback is harder.** Newly applied migrations are not automatically reversible. If the new build is incompatible with the old code:

1. Stop the new container.
2. Restore the database snapshot taken in step 3 of pre-upgrade.
3. Start the previous image against the restored database.

This is why the pre-upgrade snapshot is non-negotiable.

## Verifying after upgrade

Beyond the smoke-test:

* Check structured logs for new error codes you don't recognize.
* Run `get_database_health_metrics` — flag any recommendations that weren't there before the upgrade.
* Confirm tenant queries still scope correctly (RLS deployments).
* Watch latency dashboards for 24 hours before declaring success.

## See also

* [Release Notes](/vconic-for-resellers/07-release-notes)
* [Migration Guide](/reference/migration_guide)
* [Changelog](/reference/changelog)


# Release Notes

**Audience:** Reseller-facing summary of shipped VCONIC versions. For the canonical, developer-oriented changelog see [CHANGELOG.md](/reference/changelog).

> Versions track the underlying `vcon-mcp` package. The current published version is read from [`package.json`](https://github.com/vcon-dev/vcon-mcp/blob/main/package.json).

## Current version

### 1.2.0

**Highlights**

* Predictable vCon contract tools (deterministic shape for AI-client use)
* Strolid sync helper bundled for legacy vCon corpora ingestion
* REST API parity with the MCP tool surface
* Embedded API-key authentication for both REST and MCP HTTP transports
* Build provenance exposed via `X-Version`, `X-Git-Commit`, `X-Build-Time` response headers
* VitePress documentation site

**Compatibility**

| Component               | Tested with        |
| ----------------------- | ------------------ |
| Docker Engine           | 24+                |
| PostgreSQL              | 14+ (via Supabase) |
| Node.js (source builds) | 20+                |
| MCP protocol            | 1.x                |

**Known issues**

* Cold-start `search_vcons_content` queries on large corpora can exceed 30s on first run. Steady-state is sub-second once indexes are warm.
* Semantic search requires `OPENAI_API_KEY` (or LiteLLM) plus a one-time embedding backfill via `npm run sync:embeddings`.

**Upgrade notes**

Standard stop-the-world procedure — see [Upgrade Guide](/vconic-for-resellers/06-upgrade-guide). No new required env vars over 1.1.x.

## Prior versions

For the full version history, including 1.0.x and 1.1.x details, see the canonical [Changelog](/reference/changelog).

***

## Release-notes template (for future versions)

Use this skeleton for each new VCONIC release entry.

```markdown
### X.Y.Z

**Highlights**

- One sentence per shipped feature

**New environment variables**

| Variable | Default | Meaning |
|---|---|---|
| `NEW_VAR` | `default` | What it controls |

**Breaking changes**

- Explicit list. Mark any that require a code or config change at the
  customer site.

**Migration steps**

1. Concrete commands or config changes.

**Known issues**

- Item + workaround.

**Upgrade notes**

- Anything beyond the standard procedure.
```

## See also

* [Upgrade Guide](/vconic-for-resellers/06-upgrade-guide)
* [Canonical changelog](/reference/changelog)
* [Migration Guide](/reference/migration_guide)


# Overview

Complete technical specifications, standards, and quick references for the vCon MCP Server.

## Overview

This reference section provides authoritative technical documentation for:

* **IETF vCon Specifications** - Complete standard definitions
* **Database Schema** - PostgreSQL table structures and relationships
* **MCP Protocol** - Model Context Protocol integration details
* **API Standards** - Tool, resource, and prompt specifications
* **Compliance Matrices** - Regulatory framework mappings
* **Quick References** - Fast lookup guides for common tasks

***

## Essential References

### 🎯 Quick Start References

| Document                                                                                        | Purpose                              | Time   | Audience       |
| ----------------------------------------------------------------------------------------------- | ------------------------------------ | ------ | -------------- |
| [Quick Reference](/reference/quick_reference)                                                   | Critical field corrections checklist | 5 min  | All developers |
| [Glossary](/reference/glossary)                                                                 | Terms and definitions                | -      | All users      |
| [CLI Reference](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/cli-reference.md) | Command-line tool usage              | 10 min | Developers     |

### 📋 Specification References

| Document                                                                                      | Purpose                                     | Time   | Audience     |
| --------------------------------------------------------------------------------------------- | ------------------------------------------- | ------ | ------------ |
| [IETF vCon Core](/reference/vcon-spec)                                                        | Complete vCon specification                 | 45 min | Implementers |
| [MCP Protocol](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-protocol.md) | Model Context Protocol details              | 30 min | Integrators  |
| [Agent database schema](/reference/agent_database_schema)                                     | Full PostgreSQL schema (matches migrations) | 25 min | DBAs, agents |
| [Corrected schema (IETF)](/reference/corrected_schema)                                        | IETF-oriented DDL narrative                 | 20 min | DBAs         |
| [Search tools](/guide/search)                                                                 | MCP search tools and behavior               | 15 min | Developers   |

### 🔧 Implementation References

| Document                                                                                                | Purpose                            | Time   | Audience         |
| ------------------------------------------------------------------------------------------------------- | ---------------------------------- | ------ | ---------------- |
| [Implementation Corrections](/reference/implementation_corrections)                                     | Known issues and fixes             | 15 min | Developers       |
| [Migration Guide](/reference/migration_guide)                                                           | Upgrading existing implementations | 30 min | Migrators        |
| [Compliance Matrix](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/compliance-matrix.md) | Regulatory requirements mapping    | 20 min | Compliance teams |

### 📚 Feature References

| Document                                                                                                    | Purpose                      | Time   | Audience             |
| ----------------------------------------------------------------------------------------------------------- | ---------------------------- | ------ | -------------------- |
| [Open Source Features](/reference/features)                                                                 | Core functionality reference | 30 min | All users            |
| [Enterprise Features](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/enterprise-features.md) | Proprietary capabilities     | 30 min | Enterprise customers |
| [Plugin Architecture](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/plugin-architecture.md) | Extension system design      | 20 min | Plugin developers    |

***

## By Use Case

### 🎯 "I'm implementing vCon for the first time"

1. **Start here:** [Quick Reference](/reference/quick_reference) - Know what to avoid
2. **Read:** [IETF vCon Core](/reference/vcon-spec) - Understand the standard
3. **Reference:** [Agent database schema](/reference/agent_database_schema) - Implement storage
4. **Verify:** [Implementation Corrections](/reference/implementation_corrections) - Check for issues

### 🔄 "I'm migrating existing vCon code"

1. **Audit:** [Implementation Corrections](/reference/implementation_corrections) - Identify issues
2. **Plan:** [Migration Guide](/reference/migration_guide) - Follow migration steps
3. **Verify:** [Quick Reference](/reference/quick_reference) - Confirm compliance
4. **Test:** [Testing Reference](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/testing-reference.md) - Run compliance tests

### 🔍 "I'm reviewing vCon code"

1. **Quick check:** [Quick Reference](/reference/quick_reference) - Fast verification
2. **Deep check:** [Implementation Corrections](/reference/implementation_corrections) - Known issues
3. **Schema check:** [Agent database schema](/reference/agent_database_schema) - Database compliance
4. **Standards check:** [vCon Spec](/reference/vcon-spec) - Spec adherence

### 🛠️ "I'm integrating with MCP"

1. **Protocol:** [MCP Protocol](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-protocol.md) - Understanding MCP
2. **Tools:** [../api/tools.md](/api-reference/tools) - Available tools
3. **Resources:** [../api/resources.md](/api-reference/resources) - Resource URIs
4. **Prompts:** [../api/prompts.md](/api-reference/prompts) - Query templates

### 📊 "I need compliance documentation"

1. **Overview:** [Compliance Matrix](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/compliance-matrix.md) - All regulations
2. **GDPR:** GDPR-specific mappings
3. **CCPA:** CCPA-specific mappings
4. **HIPAA:** HIPAA-specific mappings

***

## Reference Categories

### 📖 Standards & Specifications

#### IETF vCon Standard

* [**vCon Core Specification**](/reference/vcon-spec) - Complete IETF draft reference
  * Main vCon object structure
  * Party, Dialog, Analysis, Attachment objects
  * Required vs optional fields
  * Encoding options
  * Extensions and must\_support
* [**vCon Data Types**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/vcon-data-types.md) - Type definitions and validation
  * TypeScript interfaces
  * Zod schemas
  * Validation rules
  * Example objects

#### MCP Protocol

* [**MCP Protocol Reference**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-protocol.md) - Complete MCP documentation
  * Server capabilities
  * Tool invocation
  * Resource access
  * Prompt templates
  * Error handling
* [**MCP Integration Guide**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-integration.md) - How to integrate with MCP clients
  * Claude Desktop setup
  * Custom client development
  * Protocol compliance
  * Testing tools

### 🗄️ Database & Storage

* [**Agent database schema**](/reference/agent_database_schema) - Deployed PostgreSQL schema (authoritative for agents)
  * Core and operational tables, MVs, tenant columns, RLS summary
  * Pointers to migrations for RPC signatures
* [**Corrected schema**](/reference/corrected_schema) - IETF-oriented DDL (not the full catalog)
* [**Search tools**](/guide/search) - MCP search tools
  * Keyword, semantic, hybrid, tags
* **Migrations** under `supabase/migrations/` - Source of truth for `search_vcons_*` SQL functions and index definitions

### 🔧 Implementation Guides

* [**Implementation Corrections**](/reference/implementation_corrections) - Known issues and fixes
* [**Migration Guide**](/reference/migration_guide) - Upgrading from older versions
* [**Testing Reference**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/testing-reference.md) - Compliance and validation tests
* [**Error Reference**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/error-reference.md) - Error codes and handling

### 📋 Quick References

* [**Quick Reference**](/reference/quick_reference) - Critical corrections checklist
* [**CLI Reference**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/cli-reference.md) - Command-line tools
* [**Glossary**](/reference/glossary) - Terms and definitions
* [**FAQ**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/faq.md) - Frequently asked questions

### ✅ Compliance & Standards

* [**Compliance Matrix**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/compliance-matrix.md) - All regulatory frameworks
* [**GDPR Compliance**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/gdpr-compliance.md) - GDPR-specific details
* [**CCPA Compliance**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/ccpa-compliance.md) - CCPA-specific details
* [**HIPAA Compliance**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/hipaa-compliance.md) - HIPAA-specific details
* [**Security Standards**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/security-standards.md) - Security best practices

### 🎨 Feature References

* [**Open Source Features**](/reference/features) - Core functionality
* [**Enterprise Features**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/enterprise-features.md) - Proprietary features
* [**Plugin Architecture**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/plugin-architecture.md) - Extension system
* [**Roadmap**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/roadmap.md) - Future features and plans

***

## Critical Corrections Summary

This implementation fixes 7 critical issues found in many vCon implementations:

1. ✅ **Analysis Schema Field** - Uses `schema` not `schema_version` (Section 4.5.6)
2. ✅ **Analysis Vendor Requirement** - `vendor` is required, not optional (Section 4.5.5)
3. ✅ **Analysis Body Type** - `body` is string type, not object (Section 4.5.7)
4. ✅ **Party UUID Field** - Added per spec Section 4.2.12
5. ✅ **Encoding Defaults** - No default values, explicit only
6. ✅ **Dialog Type Constraints** - Must be one of 4 valid types (Section 4.3.1)
7. ✅ **Dialog New Fields** - Added `session_id`, `application`, `message_id`

**See** [**Quick Reference**](/reference/quick_reference) **for detailed checklist.**

***

## Specification Sources

### Primary Sources

* **IETF vCon Core:** `draft-ietf-vcon-vcon-core-02`
  * Location: `../background_docs/draft-ietf-vcon-vcon-core-02.txt`
  * Working Group: <https://datatracker.ietf.org/wg/vcon/>
* **IETF vCon Privacy Primer:** `draft-ietf-vcon-privacy-primer-00`
  * Location: `../background_docs/draft-ietf-vcon-privacy-primer-00.txt`
* **vCon Consent (Draft):** `draft-howe-vcon-consent-00`
  * Location: `../background_docs/draft-howe-vcon-consent-00.txt`

### Related Standards

* **SCITT Architecture:** `draft-ietf-scitt-architecture-15`
  * For transparency service integration
  * Location: `../background_docs/draft-ietf-scitt-architecture-15.txt`
* **AI Preferences Vocabulary:** `draft-ietf-aipref-vocab-01`
  * For AI-related metadata
  * Location: `../background_docs/draft-ietf-aipref-vocab-01.txt`

***

## Version Information

### Current Version

* **Server Version:** 1.2.0
* **vCon Spec Version:** 0.4.0 (draft-ietf-vcon-vcon-core-02)
* **Schema Version:** 1.2.0
* **Last Updated:** April 2026

### Version History

See [Changelog](/reference/changelog) for complete version history.

### Compatibility

* **Node.js:** 18.x or higher
* **PostgreSQL:** 15.x or higher
* **Supabase:** Latest stable
* **MCP SDK:** 0.4.x

***

## Contributing to Reference Docs

### Reporting Issues

Found an error in the reference documentation?

1. Check if it's already in [Implementation Corrections](/reference/implementation_corrections)
2. Open an issue on GitHub with:
   * Document name and section
   * Expected vs actual content
   * IETF spec reference (if applicable)

### Submitting Updates

To update reference documentation:

1. Verify against IETF spec
2. Update relevant markdown file
3. Update cross-references
4. Submit pull request with changes

See [Contributing Guide](/development/contributing) for details.

***

## Additional Resources

### Documentation

* [**User Guides**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/guide/README.md) - How to use the server
* [**API Reference**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/api/README.md) - Complete API documentation
* [**Developer Guides**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/README.md) - Building and extending
* [**Examples**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/examples/README.md) - Code examples and tutorials

### External Links

* **IETF vCon Working Group:** <https://datatracker.ietf.org/wg/vcon/>
* **MCP Protocol:** <https://modelcontextprotocol.io/>
* **Supabase Docs:** <https://supabase.com/docs>
* **pgvector:** <https://github.com/pgvector/pgvector>

### Community

* **GitHub:** <https://github.com/vcon-dev/vcon-mcp>
* **Issues:** Report bugs and request features
* **Discussions:** Ask questions and share ideas

***

## Quick Navigation

### By Role

**Developers:** [Quick Reference](/reference/quick_reference) → [vCon Spec](/reference/vcon-spec) → [Agent database schema](/reference/agent_database_schema) → [API Docs](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/api/README.md)

**DBAs:** [Agent database schema](/reference/agent_database_schema) → [Search tools](/guide/search) → [Performance Tuning](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/performance.md)

**Integrators:** [MCP Protocol](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-protocol.md) → [API Reference](/api-reference/tools) → [Integration Guide](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-integration.md)

**Compliance Teams:** [Compliance Matrix](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/compliance-matrix.md) → [GDPR](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/gdpr-compliance.md) → [CCPA](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/ccpa-compliance.md)

### By Task

**Setting up:** [Quick Start](/guide/getting-started) → [Agent database schema](/reference/agent_database_schema) → [Testing](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/testing-reference.md)

**Migrating:** [Implementation Corrections](/reference/implementation_corrections) → [Migration Guide](/reference/migration_guide) → [Testing](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/testing-reference.md)

**Extending:** [Plugin Architecture](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/plugin-architecture.md) → [Custom Tools](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/development/custom-tools.md) → [API Reference](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/api/README.md)

**Troubleshooting:** [Error Reference](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/error-reference.md) → [FAQ](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/faq.md) → [GitHub Issues](https://github.com/vcon-dev/vcon-mcp/issues)

***

**Need help?** Check the [FAQ](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/faq.md) or ask in [GitHub Discussions](https://github.com/vcon-dev/vcon-mcp/discussions).

**Found an issue?** Report it in [GitHub Issues](https://github.com/vcon-dev/vcon-mcp/issues) with the `documentation` label.

***

*Reference documentation is the authoritative source for implementation details. When in doubt, consult the IETF specifications.*


# vCon Specification

Complete reference for the IETF vCon (Virtual Conversation) standard.

## Overview

**Specification:** `draft-ietf-vcon-vcon-core-02`\
**Version:** 0.4.0\
**Working Group:** IETF vCon WG\
**Status:** Internet-Draft\
**Full Text:** [../background\_docs/draft-ietf-vcon-vcon-core-00.txt](https://github.com/vcon-dev/vcon-mcp/blob/main/background_docs/draft-ietf-vcon-vcon-core-00.txt) (v0.3.0 reference; v0.4.0 spec in project background-docs)

The vCon (Virtual Conversation) is a standard container format for storing conversation data in a structured, interoperable way. It supports voice calls, video meetings, text chats, emails, and other communication forms.

***

## Table of Contents

1. [Core Concepts](#core-concepts)
2. [Main vCon Object](#main-vcon-object)
3. [Party Object](#party-object)
4. [Dialog Object](#dialog-object)
5. [Attachment Object](#attachment-object)
6. [Analysis Object](#analysis-object)
7. [Encoding Options](#encoding-options)
8. [Extensions](#extensions)
9. [Security](#security)

***

## Core Concepts

### What is a vCon?

A vCon is a JSON object that contains:

* **Metadata** - Subject, timestamps, identifiers
* **Parties** - Participants in the conversation
* **Dialog** - The actual conversation content (audio, text, video)
* **Attachments** - Supporting files and metadata (tags, notes)
* **Analysis** - AI/ML analysis results (transcripts, sentiment, summary)

### Key Principles

1. **Self-contained** - All conversation data in one object
2. **Interoperable** - Standard format across systems
3. **Extensible** - Support for custom data via extensions
4. **Secure** - Support for signing (JWS) and encryption (JWE)
5. **Flexible** - Support for any communication medium

### Use Cases

* **Call recording storage** - Phone, video, web calls
* **Chat archival** - Text conversations, emails
* **Compliance** - GDPR, CCPA, HIPAA record keeping
* **Analytics** - Conversation intelligence and insights
* **Training** - Agent training data
* **Legal** - Dispute resolution and evidence

***

## Main vCon Object

**Section 4.1** of the IETF spec defines the top-level vCon structure.

### Required Fields

```typescript
interface VCon {
  // REQUIRED
  vcon: string;           // Version (e.g., "0.4.0")
  uuid: string;           // Unique identifier (RFC 4122)
  created_at: string;     // ISO 8601 timestamp
  parties: Party[];       // At least one party required
}
```

### Optional Fields

```typescript
interface VCon {
  // Optional metadata
  subject?: string;        // Conversation subject/title
  updated_at?: string;     // Last modification timestamp
  
  // Optional content
  dialog?: Dialog[];       // Conversation content
  analysis?: Analysis[];   // AI/ML analysis results
  attachments?: Attachment[]; // Files, notes, metadata
  
  // Optional advanced features
  redacted?: RedactedInfo;    // Redaction information
  amended?: AmendedInfo;      // Append-only chain info (v0.4.0; was 'appended')
  group?: GroupInfo[];        // Group conversation info
  
  // Extension support (Section 4.1.3, 4.1.4)
  extensions?: string[];      // Extension identifiers
  critical?: string[];        // Required extensions (v0.4.0; was 'must_support')
}
```

### Field Definitions

#### vcon (string, required)

Version of the vCon specification. Current version is `"0.4.0"`.

```json
{
  "vcon": "0.4.0"
}
```

#### uuid (string, required)

Unique identifier for the vCon. Must be a valid UUID per RFC 4122.

```json
{
  "uuid": "01234567-89ab-cdef-0123-456789abcdef"
}
```

#### created\_at (string, required)

When the vCon was created. ISO 8601 format with timezone.

```json
{
  "created_at": "2025-01-15T10:30:00Z"
}
```

#### subject (string, optional)

Human-readable title or subject for the conversation.

```json
{
  "subject": "Customer Support - Billing Inquiry"
}
```

#### extensions (array, optional)

**Section 4.1.3** - List of extension identifiers this vCon uses.

```json
{
  "extensions": ["privacy-v1", "custom-metadata"]
}
```

#### critical (array, optional)

**Section 4.1.4** - Extensions that MUST be understood to process this vCon. Renamed from `must_support` in v0.4.0.

```json
{
  "critical": ["required-extension-v1"]
}
```

***

## Party Object

**Section 4.2** - Represents a participant in the conversation.

### Structure

```typescript
interface Party {
  // Contact information
  tel?: string;           // Telephone number (E.164 format)
  stir?: string;          // STIR information
  mailto?: string;        // Email address
  name?: string;          // Display name
  
  // Identity
  sip?: string;           // SIP URI
  did?: string;           // Decentralized Identifier (Section 4.2.6)
  uuid?: string;          // UUID for this party (Section 4.2.12)
  validation?: string;    // Validation method/proof
  
  // Extended information
  jcard?: object;         // vCard in JSON format
  gmlpos?: string;        // Geographic location (GML)
  civicaddress?: object;  // Civic address
  timezone?: string;      // IANA timezone
}
```

### Examples

**Phone call participant:**

```json
{
  "tel": "+12025551234",
  "name": "John Smith"
}
```

**Email participant:**

```json
{
  "mailto": "customer@example.com",
  "name": "Alice Johnson"
}
```

**Full featured party:**

```json
{
  "name": "Bob Williams",
  "tel": "+12025555678",
  "mailto": "bob@company.com",
  "uuid": "123e4567-e89b-12d3-a456-426614174000",
  "timezone": "America/New_York"
}
```

***

## Dialog Object

**Section 4.3** - Represents conversation content.

### Required Fields

```typescript
interface Dialog {
  type: DialogType;  // REQUIRED
}

type DialogType = 'recording' | 'text' | 'transfer' | 'incomplete';
```

### Optional Fields

```typescript
interface Dialog {
  // Timing
  start?: string;      // ISO 8601 start time
  duration?: number;   // Duration in seconds
  
  // Participants
  parties?: number | number[] | (number | number[])[]; // Party indexes
  originator?: number; // Party index of originator
  
  // Content
  mediatype?: string;  // Media type (v0.4.0; was 'mimetype')
  filename?: string;   // Filename
  body?: string;       // Inline content
  encoding?: Encoding; // Content encoding
  url?: string;        // External URL
  
  // Metadata
  content_hash?: string | string[]; // Content hash
  disposition?: Disposition;  // Call disposition
  session_id?: { local: string; remote: string }; // Session identifier (v0.4.0; was string)
  application?: string;       // Application name (Section 4.3.13)
  message_id?: string;        // Message ID (Section 4.3.14)
}

type Encoding = 'none' | 'base64url' | 'json';
type Disposition = 'no-answer' | 'congestion' | 'failed' | 'busy' | 
                   'hung-up' | 'voicemail-no-message';
```

### Dialog Types

#### recording

Audio or video recording of the conversation.

```json
{
  "type": "recording",
  "start": "2025-01-15T10:30:00Z",
  "duration": 125.4,
  "parties": [0, 1],
  "originator": 0,
  "mediatype": "audio/wav",
  "filename": "call-recording.wav",
  "url": "https://storage.example.com/recording.wav"
}
```

#### text

Text-based conversation (chat, SMS, email body).

```json
{
  "type": "text",
  "start": "2025-01-15T10:32:15Z",
  "parties": 0,
  "body": "Hello, I need help with my account.",
  "encoding": "none"
}
```

#### transfer

Reference to another vCon (call transfer, forwarding).

```json
{
  "type": "transfer",
  "start": "2025-01-15T10:35:00Z",
  "parties": [0, 2],
  "body": "01234567-89ab-cdef-0123-456789abcdef",
  "encoding": "none"
}
```

#### incomplete

Partial or failed conversation.

```json
{
  "type": "incomplete",
  "start": "2025-01-15T10:30:00Z",
  "disposition": "no-answer",
  "parties": [0, 1]
}
```

***

## Attachment Object

**Section 4.4** - Supporting files and metadata.

### Structure

```typescript
interface Attachment {
  // Timing and context
  type?: string;       // Attachment type (custom)
  start?: string;      // ISO 8601 timestamp
  party?: number;      // Associated party index
  dialog?: number;     // Associated dialog index
  
  // Content
  mediatype?: string;  // Media type (v0.4.0; was 'mimetype')
  filename?: string;   // Filename
  body?: string;       // Inline content
  encoding?: Encoding; // Content encoding
  url?: string;        // External URL
  
  // Verification
  content_hash?: string | string[]; // Content hash
}
```

### Common Attachment Types

#### Tags Attachment

Special attachment type for key-value metadata (used by search).

```json
{
  "type": "tags",
  "encoding": "json",
  "body": "[\"department:support\", \"priority:high\", \"status:open\"]"
}
```

#### Document Attachment

Supporting document or file.

```json
{
  "type": "document",
  "start": "2025-01-15T10:30:00Z",
  "mimetype": "application/pdf",
  "filename": "invoice.pdf",
  "url": "https://storage.example.com/invoice.pdf"
}
```

#### Note Attachment

Human-added notes or annotations.

```json
{
  "type": "note",
  "party": 1,
  "start": "2025-01-15T10:35:00Z",
  "body": "Customer was satisfied with resolution",
  "encoding": "none"
}
```

***

## Analysis Object

**Section 4.5** - AI/ML analysis results.

### Required Fields

```typescript
interface Analysis {
  type: string;    // REQUIRED - Analysis type
  vendor: string;  // REQUIRED - Vendor who produced this (Section 4.5.5)
}
```

### Optional Fields

```typescript
interface Analysis {
  // Context
  dialog?: number | number[]; // Associated dialog(s)
  
  // Metadata
  product?: string;   // Specific product/model used
  schema?: string;    // Schema identifier (Section 4.5.6) ⚠️ NOT schema_version
  
  // Content
  mediatype?: string; // Media type (v0.4.0; was 'mimetype')
  filename?: string;  // Filename
  body?: string;      // Analysis result (Section 4.5.7) ⚠️ STRING not object
  encoding?: Encoding; // Content encoding
  url?: string;       // External URL
  
  // Verification
  content_hash?: string | string[]; // Content hash
}
```

### Critical Corrections

⚠️ **Common Mistakes:**

1. Using `schema_version` - WRONG. Use `schema` (Section 4.5.6)
2. Making `vendor` optional - WRONG. It's REQUIRED (Section 4.5.5)
3. Using `object` type for `body` - WRONG. Use `string` (Section 4.5.7)

### Examples

**Transcript analysis:**

```json
{
  "type": "transcript",
  "vendor": "Deepgram",
  "product": "Nova-2",
  "schema": "v1",
  "dialog": 0,
  "body": "Hello, I need help with my account. Sure, I can help...",
  "encoding": "none"
}
```

**Sentiment analysis:**

```json
{
  "type": "sentiment",
  "vendor": "OpenAI",
  "product": "gpt-4",
  "dialog": [0, 1, 2],
  "body": "{\"sentiment\": \"positive\", \"score\": 0.85}",
  "encoding": "json"
}
```

**Summary:**

```json
{
  "type": "summary",
  "vendor": "CustomAI",
  "schema": "summary-v2",
  "body": "Customer inquired about billing. Issue resolved by providing refund.",
  "encoding": "none"
}
```

***

## Encoding Options

**Section 4.3.6, 4.4.7, 4.5.8** - Content encoding types.

### none

Raw text content, no encoding.

```json
{
  "body": "Plain text content",
  "encoding": "none"
}
```

### base64url

Base64 URL-safe encoding (RFC 4648).

```json
{
  "body": "SGVsbG8gV29ybGQh",
  "encoding": "base64url"
}
```

### json

JSON-formatted content.

```json
{
  "body": "{\"key\": \"value\"}",
  "encoding": "json"
}
```

### Important

⚠️ **NO DEFAULT VALUES** - `encoding` field should NOT have a default value in database schema or type definitions. It must be explicitly set.

***

## Extensions

**Section 4.1.3, 4.1.4** - Supporting custom functionality.

### extensions Array

List of extension identifiers used in this vCon.

```json
{
  "extensions": [
    "privacy-redaction-v1",
    "custom-analytics-v2"
  ]
}
```

### critical Array

Extensions that MUST be understood to process this vCon correctly. Renamed from `must_support` in v0.4.0.

```json
{
  "critical": [
    "required-extension-v1"
  ]
}
```

**Processing Rules:**

1. If a vCon has `critical` entries you don't understand, reject it
2. If a vCon has `extensions` you don't understand, you MAY process it
3. Always preserve unrecognized extension data

***

## Security

### Signing (JWS)

vCons can be signed using JSON Web Signature (JWS):

```json
{
  "payload": "base64url(vcon_json)",
  "signatures": [{
    "protected": "base64url(header)",
    "signature": "base64url(signature)"
  }]
}
```

### Encryption (JWE)

vCons can be encrypted using JSON Web Encryption (JWE):

```json
{
  "protected": "base64url(header)",
  "encrypted_key": "base64url(key)",
  "iv": "base64url(iv)",
  "ciphertext": "base64url(encrypted_vcon)",
  "tag": "base64url(tag)"
}
```

### Content Hashing

All content fields (body, url) can have `content_hash` for verification:

```json
{
  "body": "content",
  "content_hash": "sha256:abc123..."
}
```

***

## Complete Example

**Minimal vCon:**

```json
{
  "vcon": "0.4.0",
  "uuid": "01234567-89ab-cdef-0123-456789abcdef",
  "created_at": "2025-01-15T10:30:00Z",
  "parties": [
    {
      "name": "Alice",
      "mailto": "alice@example.com"
    }
  ]
}
```

**Full-featured vCon:**

```json
{
  "vcon": "0.4.0",
  "uuid": "01234567-89ab-cdef-0123-456789abcdef",
  "created_at": "2025-01-15T10:30:00Z",
  "updated_at": "2025-01-15T10:35:00Z",
  "subject": "Customer Support Call - Billing Issue",
  "parties": [
    {
      "tel": "+12025551234",
      "name": "Customer",
      "uuid": "123e4567-e89b-12d3-a456-426614174000"
    },
    {
      "tel": "+12025555678",
      "name": "Agent Sarah",
      "uuid": "234e5678-e89b-12d3-a456-426614174001"
    }
  ],
  "dialog": [
    {
      "type": "recording",
      "start": "2025-01-15T10:30:00Z",
      "duration": 180,
      "parties": [0, 1],
      "originator": 0,
      "mediatype": "audio/wav",
      "url": "https://storage.example.com/call.wav"
    },
    {
      "type": "text",
      "start": "2025-01-15T10:30:05Z",
      "parties": 0,
      "body": "I was charged twice this month",
      "encoding": "none"
    }
  ],
  "analysis": [
    {
      "type": "transcript",
      "vendor": "Deepgram",
      "product": "Nova-2",
      "dialog": 0,
      "body": "Customer: I was charged twice... Agent: I can help...",
      "encoding": "none"
    },
    {
      "type": "summary",
      "vendor": "OpenAI",
      "product": "gpt-4",
      "body": "Customer reported duplicate charge. Refund processed.",
      "encoding": "none"
    }
  ],
  "attachments": [
    {
      "type": "tags",
      "encoding": "json",
      "body": "[\"department:billing\", \"status:resolved\"]"
    }
  ]
}
```

***

## Validation Rules

### Required Validations

1. ✅ `vcon` field must be `"0.4.0"`
2. ✅ `uuid` must be valid UUID format
3. ✅ `created_at` must be ISO 8601 timestamp
4. ✅ `parties` array must have at least one party
5. ✅ Dialog `type` must be one of 4 valid types
6. ✅ Analysis `vendor` must be provided

### Reference Validations

1. ✅ Party indexes in `dialog.parties` must be valid
2. ✅ Dialog indexes in `analysis.dialog` must be valid
3. ✅ Party indexes in `attachment.party` must be valid
4. ✅ Dialog indexes in `attachment.dialog` must be valid

### Format Validations

1. ✅ Timestamps must be ISO 8601 with timezone
2. ✅ UUIDs must be RFC 4122 format
3. ✅ `encoding` must be one of: `none`, `base64url`, `json`
4. ✅ Phone numbers should be E.164 format

***

## Additional Resources

* **Full Specification:** [../background\_docs/draft-ietf-vcon-vcon-core-00.txt](https://github.com/vcon-dev/vcon-mcp/blob/main/background_docs/draft-ietf-vcon-vcon-core-00.txt)
* **Privacy Primer:** [../background\_docs/draft-ietf-vcon-privacy-primer-00.txt](https://github.com/vcon-dev/vcon-mcp/blob/main/background_docs/draft-ietf-vcon-privacy-primer-00.txt)
* **IETF Working Group:** <https://datatracker.ietf.org/wg/vcon/>
* **Quick Reference:** [QUICK\_REFERENCE.md](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/QUICK_REFERENCE.md)
* **Database Schema:** [CORRECTED\_SCHEMA.md](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/CORRECTED_SCHEMA.md)

***

*This reference is based on draft-ietf-vcon-vcon-core-02 (v0.4.0) and reflects all corrections identified in* [*IMPLEMENTATION\_CORRECTIONS.md*](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/IMPLEMENTATION_CORRECTIONS.md)*.*


# Database Schema

**Purpose:** Single place to understand what exists in the vCon MCP Supabase database after all migrations in `supabase/migrations/` have been applied.

**Not a substitute for migrations.** If this document disagrees with SQL in `supabase/migrations/`, the migrations win. Reconcile by reading migrations in timestamp order or by introspecting a live database.

**Related:** IETF field naming and v0.4.0 semantics are summarized in [QUICK\_REFERENCE.md](/reference/quick_reference). MCP search tools are described in [Search tools guide](/guide/search). PostgreSQL RPC signatures live in `supabase/migrations/` (see migrations that define `search_vcons_keyword`, `search_vcons_semantic`, and related functions).

***

## 1. Extensions

Typical extensions enabled (see early migrations):

| Extension                | Use                                                             |
| ------------------------ | --------------------------------------------------------------- |
| `uuid-ossp` / `pgcrypto` | UUID generation (`gen_random_uuid()`)                           |
| `pg_trgm`                | Trigram and GIN ops (often under schema `extensions`)           |
| `vector`                 | `pgvector` embeddings (`vector(384)` after dimension migration) |

***

## 2. Core vCon tables (normalized)

Each of `vcons`, `parties`, `dialog`, `analysis`, `attachments` also has a nullable `extra JSONB` holding input keys with no column of their own; the reader merges it back and never returns `extra` itself.

### `vcons`

Root row per vCon. Internal primary key is `id`; `uuid` is the vCon document UUID.

| Column                                 | Type        | Notes                                                                                                     |
| -------------------------------------- | ----------- | --------------------------------------------------------------------------------------------------------- |
| `id`                                   | UUID        | PK                                                                                                        |
| `uuid`                                 | UUID        | Unique vCon id (document)                                                                                 |
| `vcon_version`                         | VARCHAR(10) | DB default from initial migration is still `'0.3.0'` unless changed; **application code targets `0.4.0`** |
| `subject`                              | TEXT        |                                                                                                           |
| `created_at`, `updated_at`             | TIMESTAMPTZ |                                                                                                           |
| `basename`, `filename`                 | TEXT        |                                                                                                           |
| `done`, `corrupt`                      | BOOLEAN     |                                                                                                           |
| `processed_by`                         | TEXT        |                                                                                                           |
| `privacy_processed`, `redaction_rules` | JSONB       | Privacy extension                                                                                         |
| `redacted`                             | JSONB       |                                                                                                           |
| `group_data`                           | JSONB       |                                                                                                           |
| `extensions`                           | TEXT\[]     |                                                                                                           |
| `must_support`                         | TEXT\[]     | **Deprecated** name; kept in sync with `critical` (see below)                                             |
| `critical`                             | TEXT\[]     | v0.4.0 name (Section 4.1.4)                                                                               |
| `appended`                             | JSONB       | **Deprecated** name; kept in sync with `amended`                                                          |
| `amended`                              | JSONB       | v0.4.0 name (Section 4.1.9)                                                                               |
| `tenant_id`                            | TEXT        | Multi-tenant scope; `NULL` can mean shared (see RLS)                                                      |
| `subject_tsvector`                     | TSVECTOR    | Materialized for FTS; maintained by trigger                                                               |

**Triggers:** `sync_deprecated_fields_trigger` keeps `must_support`/`critical` and `appended`/`amended` aligned during transition.

**Views:** `vcons_legacy` exposes old column names; `vcon_field_usage` shows which side is populated.

***

### `parties`

| Column                                                      | Type     | Notes                                                                   |
| ----------------------------------------------------------- | -------- | ----------------------------------------------------------------------- |
| `id`                                                        | UUID     | PK                                                                      |
| `vcon_id`                                                   | UUID     | FK → `vcons(id)` CASCADE                                                |
| `party_index`                                               | INTEGER  | Index in vCon `parties` array                                           |
| `tel`, `sip`, `stir`, `mailto`, `name`, `did`, `validation` | TEXT     |                                                                         |
| `jcard`                                                     | JSONB    |                                                                         |
| `gmlpos`, `timezone`                                        | TEXT     |                                                                         |
| `civicaddress`                                              | JSONB    |                                                                         |
| `uuid`                                                      | TEXT     | **Not a UUID type:** migration widened to TEXT for flexible identifiers |
| `data_subject_id`                                           | TEXT     | Privacy                                                                 |
| `metadata`                                                  | JSONB    |                                                                         |
| `tenant_id`                                                 | TEXT     | Denormalized for RLS                                                    |
| `party_tsvector`                                            | TSVECTOR | FTS helper                                                              |

Unique: `(vcon_id, party_index)`.

***

### `dialog`

| Column                                                         | Type        | Notes                                                           |
| -------------------------------------------------------------- | ----------- | --------------------------------------------------------------- |
| `id`                                                           | UUID        | PK                                                              |
| `vcon_id`                                                      | UUID        | FK → `vcons(id)` CASCADE                                        |
| `dialog_index`                                                 | INTEGER     |                                                                 |
| `type`                                                         | TEXT        | CHECK: `recording`, `text`, `transfer`, `incomplete`            |
| `start_time`                                                   | TIMESTAMPTZ |                                                                 |
| `duration_seconds`                                             | REAL        |                                                                 |
| `parties`                                                      | INTEGER\[]  | Party indices                                                   |
| `originator`                                                   | INTEGER     |                                                                 |
| `mediatype`, `filename`                                        | TEXT        |                                                                 |
| `body`, `encoding`, `url`, `content_hash`                      | TEXT        | `encoding` constrained to `base64url`, `json`, `none`, or NULL  |
| `disposition`                                                  | TEXT        | **No longer restricted** to spec enum (migration dropped CHECK) |
| `session_id`                                                   | JSONB       | v0.4.0 SessionId object shape; use this                         |
| `session_id_legacy`                                            | TEXT        | Legacy plain string column after rename                         |
| `application`, `message_id`                                    | TEXT        |                                                                 |
| `size_bytes`                                                   | BIGINT      |                                                                 |
| `metadata`                                                     | JSONB       |                                                                 |
| `transferee`, `transferor`                                     | INTEGER     | Transfer dialog (Section 4.3.12)                                |
| `transfer_target`, `original`, `consultation`, `target_dialog` | INTEGER\[]  |                                                                 |
| `tenant_id`                                                    | TEXT        |                                                                 |
| `body_tsvector`                                                | TSVECTOR    | FTS helper                                                      |

Unique: `(vcon_id, dialog_index)`.

***

### `party_history`

| Column        | Type        | Notes                                                    |
| ------------- | ----------- | -------------------------------------------------------- |
| `id`          | UUID        | PK                                                       |
| `dialog_id`   | UUID        | FK → `dialog(id)` CASCADE                                |
| `party_index` | INTEGER     |                                                          |
| `time`        | TIMESTAMPTZ |                                                          |
| `event`       | TEXT        | Includes `dtmfdown`, `dtmfup` plus join/hold/mute events |
| `dtmf`        | TEXT        | When event is DTMF                                       |
| `tenant_id`   | TEXT        |                                                          |

***

### `attachments`

| Column                                                | Type        | Notes                                                   |
| ----------------------------------------------------- | ----------- | ------------------------------------------------------- |
| `id`                                                  | UUID        | PK                                                      |
| `vcon_id`                                             | UUID        | FK → `vcons(id)` CASCADE                                |
| `attachment_index`                                    | INTEGER     |                                                         |
| `type`, `purpose`                                     | TEXT        | `purpose` added for spec alignment                      |
| `start_time`                                          | TIMESTAMPTZ |                                                         |
| `party`, `dialog`                                     | INTEGER     | Indices into parties/dialog                             |
| `mimetype`                                            | TEXT        | **Legacy column name** in DB; spec field is `mediatype` |
| `filename`, `body`, `encoding`, `url`, `content_hash` | TEXT        |                                                         |
| `size_bytes`                                          | BIGINT      |                                                         |
| `metadata`                                            | JSONB       |                                                         |
| `created_at`, `updated_at`                            | TIMESTAMPTZ | Tag rows drive MV refresh                               |
| `tenant_id`                                           | TEXT        |                                                         |

**Tags:** Stored as attachment `type = 'tags'`, `encoding = 'json'`, `body` a JSON array of `"key:value"` strings.

Unique: `(vcon_id, attachment_index)`.

**Partial index:** `idx_attachments_tags_partial ON attachments (vcon_id, body) WHERE type = 'tags'` — speeds up tag scans and `getUniqueTags` fallback path (migration `20260416000000`).

***

### `analysis`

| Column                                    | Type        | Notes                              |
| ----------------------------------------- | ----------- | ---------------------------------- |
| `id`                                      | UUID        | PK                                 |
| `vcon_id`                                 | UUID        | FK → `vcons(id)` CASCADE           |
| `analysis_index`                          | INTEGER     |                                    |
| `type`                                    | TEXT        | NOT NULL                           |
| `dialog_indices`                          | INTEGER\[]  |                                    |
| `mediatype`, `filename`                   | TEXT        |                                    |
| `vendor`                                  | TEXT        | NOT NULL                           |
| `product`, `schema`                       | TEXT        | Use `schema`, not `schema_version` |
| `body`, `encoding`, `url`, `content_hash` | TEXT        |                                    |
| `created_at`                              | TIMESTAMPTZ |                                    |
| `confidence`                              | REAL        |                                    |
| `metadata`                                | JSONB       |                                    |
| `tenant_id`                               | TEXT        |                                    |
| `body_tsvector`                           | TSVECTOR    | FTS helper                         |

Unique: `(vcon_id, analysis_index)`.

***

### `groups`

| Column                                    | Type    | Notes                    |
| ----------------------------------------- | ------- | ------------------------ |
| `id`                                      | UUID    | PK                       |
| `vcon_id`                                 | UUID    | FK → `vcons(id)` CASCADE |
| `group_index`                             | INTEGER |                          |
| `uuid`                                    | UUID    | Referenced vCon          |
| `body`, `encoding`, `url`, `content_hash` | TEXT    |                          |
| `tenant_id`                               | TEXT    |                          |

Unique: `(vcon_id, group_index)`.

***

## 3. Operational and extension tables

### `vcon_embeddings`

Semantic search vectors (dimension **384** after `switch_embeddings_to_384` migration; default model `sentence-transformers/all-MiniLM-L6-v2`).

| Column                                   | Notes                                |
| ---------------------------------------- | ------------------------------------ |
| `vcon_id`                                | FK → `vcons(id)`                     |
| `content_type`                           | e.g. `subject`, `dialog`, `analysis` |
| `content_reference`                      | e.g. dialog index as text            |
| `content_text`                           | Source text                          |
| `embedding`                              | `vector(384)`                        |
| `embedding_model`, `embedding_dimension` |                                      |
| `created_at`, `updated_at`               |                                      |
| `tenant_id`                              |                                      |

Unique `(vcon_id, content_type, content_reference)`.

***

### `embedding_queue`

| Column       | Notes        |
| ------------ | ------------ |
| `id`         | BIGSERIAL PK |
| `vcon_id`    | FK           |
| `created_at` |              |
| `tenant_id`  |              |

Trigger on `vcons` insert can enqueue work.

***

### `s3_sync_tracking`

Tracks S3 sync per vCon: `vcon_id` PK, `vcon_uuid`, `s3_key`, `synced_at`, `updated_at`, optional embedding model fields, `tenant_id`.

***

### `privacy_requests`

GDPR-style request log (no `tenant_id` in migrations). Columns include `request_id`, `party_identifier`, `request_type`, `request_status`, dates, `metadata`, etc.

***

### `migration_reports`

Internal migration audit: `migration_name`, `run_date`, counts, `report_data` JSONB. **RLS:** service-role style access only (see migration).

***

## 4. Materialized view `vcon_tags_mv`

Built from tag attachments. Typical columns (see latest MV migration, e.g. `20251210120000_optimize_mv_tags_timestamps.sql`):

| Column                             | Purpose                                       |
| ---------------------------------- | --------------------------------------------- |
| `tenant_id`                        | Tenant filter                                 |
| `vcon_id`                          |                                               |
| `tags`                             | JSONB object map from `key:value` tag strings |
| `tag_updated_at`, `tag_created_at` | From tag attachment row                       |

**Refresh:** Must be refreshed after tag changes; application or jobs should use `REFRESH MATERIALIZED VIEW CONCURRENTLY` where supported and indexed appropriately.

***

## 5. Notable views

| View               | Purpose                                                              |
| ------------------ | -------------------------------------------------------------------- |
| `vcons_legacy`     | Maps `critical`→`must_support`, `amended`→`appended` for old readers |
| `vcon_field_usage` | Inspects which legacy vs new fields are used                         |

***

## 6. Multi-tenancy and RLS

* **`tenant_id`** is denormalized onto child tables for fast policy checks.
* Policies typically allow rows where `tenant_id IS NULL OR tenant_id = get_current_tenant_id()` for role `authenticated` (see `20251122175918_create_tenant_rls_policies.sql` and later fixes).
* **NULL tenant** rows may be visible across tenants by design; confirm product expectations before writing queries.

Helper RPCs such as `set_tenant_context` / `get_current_tenant_id` appear in tenant migrations; use those definitions in migrations as source of truth.

***

## 7. Search and SQL functions

Main user-facing RPCs (signatures evolve; confirm in latest migration):

* `search_vcons_keyword`, `search_vcons_semantic` (**`vector(384)`**), `search_vcons_hybrid`
* `search_vcons_by_tags` (may include time filters)
* `backfill_search_vector_batch` for tsvector backfill
* `explain_query(q text, run_analyze boolean DEFAULT false)` → `SETOF text` — runs `EXPLAIN` or `EXPLAIN (ANALYZE, BUFFERS)` on a SELECT query and returns the plan as text lines. Cannot use `exec_sql` for this because `exec_sql` wraps queries in `SELECT jsonb_agg(...) FROM (...) t`, making EXPLAIN a subquery (migration `20260416000001`). **Note:** parameter is `run_analyze`, not `analyze` — `analyze` is a PostgreSQL reserved word.
* `exec_sql(q text, params jsonb DEFAULT '{}')` — general dynamic SQL RPC; wraps query as `SELECT jsonb_agg(row_to_json(t)) FROM (<q>) t`; cannot be used for statements like EXPLAIN
* `refresh_vcon_tags_mv()` — refreshes the `vcon_tags_mv` materialized view concurrently

Semantic search joins **`vcon_tags_mv`** for tag filtering in current implementations.

See [Search tools guide](/guide/search) and the `optimize_search_*` / `fix_search_*` migrations for behavior; for exact SQL signatures use the latest migration that defines each function.

***

## 8. Table inventory (quick)

| Kind  | Name                                                                               |
| ----- | ---------------------------------------------------------------------------------- |
| Core  | `vcons`, `parties`, `dialog`, `party_history`, `attachments`, `analysis`, `groups` |
| Ops   | `vcon_embeddings`, `embedding_queue`, `s3_sync_tracking`                           |
| Other | `privacy_requests`, `migration_reports`                                            |
| MV    | `vcon_tags_mv`                                                                     |

***

## 9. Common agent mistakes to avoid

1. **Assuming docs/api/schema.md** without checking: prefer this file or migrations.
2. **`must_support` / `appended` vs `critical` / `amended`:** write new code against **`critical`** and **`amended`**; legacy columns exist for transition.
3. **`attachments.mimetype`:** column name in DB is still `mimetype` in many deployments; API/spec use **`mediatype`**.
4. **`parties.uuid`:** type is **TEXT**, not UUID.
5. **`dialog.session_id`:** JSONB object; legacy text may live in `session_id_legacy`.
6. **Embeddings:** **384** dimensions and cosine HNSW index; do not assume 1536 unless you confirm an old branch.
7. **Tags:** not a separate table; attachment type `tags` plus MV for fast search.

***

*Last reviewed against migration set including 2026-04-14 fixes. Update this file when schema changes land.*


# Corrected Schema

## Compliant with draft-ietf-vcon-vcon-core-02 (v0.4.0)

> **Deployed database:** For the **full** Supabase schema (tenant IDs, `vcon_embeddings`, `vcon_tags_mv`, RLS, dual legacy columns, `parties.uuid` as TEXT, etc.), use [**AGENT\_DATABASE\_SCHEMA.md**](/reference/agent_database_schema). The DDL below is an **IETF-oriented** baseline and does not list every operational column or table.

> ⚠️ **Updated for v0.4.0** — Column names `appended` and `must_support` were renamed to `amended` and `critical` in spec v0.4.0. The DDL below reflects the current correct names.

```sql
-- Supabase Schema for IETF vCon - CORRECTED VERSION
-- This schema is fully compliant with draft-ietf-vcon-vcon-core-02 (v0.4.0)
-- Changes from original marked with -- CORRECTED comments

-- Enable necessary extensions
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";

-- Main vCons table
CREATE TABLE vcons (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    uuid UUID UNIQUE NOT NULL, -- The vCon UUID from the original document
    vcon_version VARCHAR(10) NOT NULL DEFAULT '0.4.0',  -- CORRECTED: Updated to latest spec version
    subject TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    
    -- Original metadata fields
    basename TEXT,
    filename TEXT,
    done BOOLEAN DEFAULT false,
    corrupt BOOLEAN DEFAULT false,
    processed_by TEXT,
    
    -- Privacy tracking fields (EXTENSION - not in core spec)
    privacy_processed JSONB DEFAULT '{}',
    redaction_rules JSONB DEFAULT '{}',
    
    -- JSON fields for complex nested data
    redacted JSONB DEFAULT '{}',
    amended JSONB DEFAULT '{}',   -- CORRECTED: v0.4.0 renamed from 'appended'
    group_data JSONB DEFAULT '[]',
    extensions TEXT[],  -- CORRECTED: Added extensions array per spec Section 4.1.3
    critical TEXT[],    -- CORRECTED: v0.4.0 renamed from 'must_support' (Section 4.1.4)
    
    CONSTRAINT valid_uuid CHECK (uuid IS NOT NULL)
);

-- Parties table (normalized for efficient searching)
CREATE TABLE parties (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    party_index INTEGER NOT NULL, -- Index in the original parties array
    
    -- Core vCon Party Object fields (Section 4.2)
    tel TEXT,
    sip TEXT,
    stir TEXT,
    mailto TEXT,
    name TEXT,
    did TEXT,  -- CORRECTED: Added DID support per spec Section 4.2.6
    validation TEXT,
    jcard JSONB,
    gmlpos TEXT,
    civicaddress JSONB,
    timezone TEXT,
    uuid UUID,  -- CORRECTED: Added uuid per spec Section 4.2.12
    
    -- EXTENSION FIELDS (not in core spec) - for privacy compliance
    data_subject_id TEXT, -- Consistent identifier across vCons for privacy
    
    -- Additional party metadata as JSON
    metadata JSONB DEFAULT '{}',
    
    UNIQUE(vcon_id, party_index)
);

-- Dialog table for conversations/recordings
CREATE TABLE dialog (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    dialog_index INTEGER NOT NULL, -- Index in the original dialog array
    
    -- Core Dialog Object fields (Section 4.3)
    type TEXT NOT NULL CHECK (type IN ('recording', 'text', 'transfer', 'incomplete')), -- CORRECTED: Added constraint per spec Section 4.3.1
    start_time TIMESTAMPTZ,
    duration_seconds REAL,
    parties INTEGER[], -- Array of party indexes
    originator INTEGER,
    mediatype TEXT,
    filename TEXT,
    
    -- Content fields
    body TEXT, -- For text dialogs or transcripts
    encoding TEXT CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none')), -- CORRECTED: Removed default, added constraint
    url TEXT,
    content_hash TEXT,
    
    -- Additional fields per spec
    disposition TEXT CHECK (disposition IS NULL OR disposition IN ('no-answer', 'congestion', 'failed', 'busy', 'hung-up', 'voicemail-no-message')),
    session_id TEXT,  -- CORRECTED: Added session_id per spec Section 4.3.10
    application TEXT,  -- CORRECTED: Added application per spec Section 4.3.13
    message_id TEXT,  -- CORRECTED: Added message_id per spec Section 4.3.14
    
    size_bytes BIGINT,
    
    -- Additional dialog metadata as JSON
    metadata JSONB DEFAULT '{}',
    
    UNIQUE(vcon_id, dialog_index)
);

-- Party history table (Section 4.3.11)
CREATE TABLE party_history (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    dialog_id UUID NOT NULL REFERENCES dialog(id) ON DELETE CASCADE,
    party_index INTEGER NOT NULL,
    time TIMESTAMPTZ NOT NULL,
    event TEXT NOT NULL CHECK (event IN ('join', 'drop', 'hold', 'unhold', 'mute', 'unmute'))
);

-- Attachments table (normalized for efficient searching)
CREATE TABLE attachments (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    attachment_index INTEGER NOT NULL, -- Index in the original attachments array
    
    -- Core Attachment Object fields (Section 4.4)
    type TEXT,
    start_time TIMESTAMPTZ,
    party INTEGER,  -- CORRECTED: Singular party index per spec Section 4.4.3
    dialog INTEGER,  -- CORRECTED: Added dialog reference per spec Section 4.4.4
    
    -- Content fields
    mediatype TEXT,  -- CORRECTED: v0.0.2+ renamed mimetype→mediatype
    filename TEXT,
    body TEXT,
    encoding TEXT CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none')), -- CORRECTED: Removed default, added constraint
    url TEXT,
    content_hash TEXT,
    
    size_bytes BIGINT,
    
    -- Additional attachment metadata as JSON
    metadata JSONB DEFAULT '{}',
    
    UNIQUE(vcon_id, attachment_index)
);

-- Analysis table (normalized for efficient searching by analysis type)
CREATE TABLE analysis (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    analysis_index INTEGER NOT NULL, -- Index in the original analysis array
    
    -- Core Analysis Object fields (Section 4.5)
    type TEXT NOT NULL, -- e.g., 'summary', 'transcript', 'translation', 'sentiment', 'tts'
    dialog_indices INTEGER[],  -- CORRECTED: Added array reference per spec Section 4.5.2
    mediatype TEXT,
    filename TEXT,
    vendor TEXT NOT NULL, -- CORRECTED: Made required per spec Section 4.5.5
    product TEXT,
    schema TEXT,  -- CORRECTED: Changed from schema_version to schema per spec Section 4.5.7
    
    -- Content fields
    body TEXT,  -- CORRECTED: Changed from JSONB to TEXT to support non-JSON analysis per spec Section 4.5.8
    encoding TEXT CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none')), -- CORRECTED: Removed default, added constraint
    url TEXT,
    content_hash TEXT,
    
    -- Additional analysis metadata
    created_at TIMESTAMPTZ,
    confidence REAL,
    metadata JSONB DEFAULT '{}',
    
    UNIQUE(vcon_id, analysis_index)
);

-- Group table for aggregated vCons (Section 4.6)
CREATE TABLE groups (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    group_index INTEGER NOT NULL,
    
    -- Core Group Object fields
    uuid UUID,  -- UUID of referenced vCon
    body TEXT,  -- Inline vCon content
    encoding TEXT CHECK (encoding = 'json'),  -- Must be 'json' per spec
    url TEXT,
    content_hash TEXT,
    
    UNIQUE(vcon_id, group_index)
);

-- EXTENSION TABLES (not in core spec) - for privacy compliance

-- Privacy requests tracking table
CREATE TABLE privacy_requests (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    request_id TEXT UNIQUE NOT NULL,
    party_identifier TEXT NOT NULL,
    party_name TEXT,
    request_type TEXT NOT NULL CHECK (request_type IN (
        'access', 'rectification', 'erasure', 'portability', 'restriction', 'objection'
    )),
    request_status TEXT NOT NULL DEFAULT 'pending' CHECK (request_status IN (
        'pending', 'in_progress', 'completed', 'rejected', 'partially_completed'
    )),
    request_date TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    completion_date TIMESTAMPTZ,
    verification_method TEXT,
    verification_date TIMESTAMPTZ,
    request_details JSONB DEFAULT '{}',
    processing_notes TEXT,
    rejection_reason TEXT,
    acknowledgment_sent_date TIMESTAMPTZ,
    response_sent_date TIMESTAMPTZ,
    response_method TEXT,
    processed_by TEXT,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    metadata JSONB DEFAULT '{}'
);

-- Create indexes for common queries
CREATE INDEX idx_vcons_uuid ON vcons(uuid);
CREATE INDEX idx_vcons_created_at ON vcons(created_at);
CREATE INDEX idx_vcons_updated_at ON vcons(updated_at);

-- Party indexes
CREATE INDEX idx_parties_vcon ON parties(vcon_id);
CREATE INDEX idx_parties_tel ON parties(tel) WHERE tel IS NOT NULL;
CREATE INDEX idx_parties_email ON parties(mailto) WHERE mailto IS NOT NULL;
CREATE INDEX idx_parties_name ON parties(name) WHERE name IS NOT NULL;
CREATE INDEX idx_parties_uuid ON parties(uuid) WHERE uuid IS NOT NULL;  -- CORRECTED: Added
CREATE INDEX idx_parties_data_subject ON parties(data_subject_id) WHERE data_subject_id IS NOT NULL;

-- Dialog indexes
CREATE INDEX idx_dialog_vcon ON dialog(vcon_id);
CREATE INDEX idx_dialog_type ON dialog(type);
CREATE INDEX idx_dialog_start ON dialog(start_time);
CREATE INDEX idx_dialog_session ON dialog(session_id) WHERE session_id IS NOT NULL;  -- CORRECTED: Added

-- Attachment indexes
CREATE INDEX idx_attachments_vcon ON attachments(vcon_id);
CREATE INDEX idx_attachments_type ON attachments(type);
CREATE INDEX idx_attachments_party ON attachments(party);
CREATE INDEX idx_attachments_dialog ON attachments(dialog);  -- CORRECTED: Added

-- Analysis indexes
CREATE INDEX idx_analysis_vcon ON analysis(vcon_id);
CREATE INDEX idx_analysis_type ON analysis(type);
CREATE INDEX idx_analysis_vendor ON analysis(vendor);
CREATE INDEX idx_analysis_product ON analysis(product) WHERE product IS NOT NULL;
CREATE INDEX idx_analysis_schema ON analysis(schema) WHERE schema IS NOT NULL;  -- CORRECTED: Renamed from schema_version
CREATE INDEX idx_analysis_dialog ON analysis USING GIN (dialog_indices);  -- CORRECTED: Added for dialog array

-- Group indexes
CREATE INDEX idx_groups_vcon ON groups(vcon_id);
CREATE INDEX idx_groups_uuid ON groups(uuid) WHERE uuid IS NOT NULL;

-- Privacy request indexes
CREATE INDEX idx_privacy_requests_party ON privacy_requests(party_identifier);
CREATE INDEX idx_privacy_requests_status ON privacy_requests(request_status);
CREATE INDEX idx_privacy_requests_type ON privacy_requests(request_type);

-- Full text search indexes
CREATE INDEX idx_vcons_subject_trgm ON vcons USING gin (subject gin_trgm_ops);
CREATE INDEX idx_parties_name_trgm ON parties USING gin (name gin_trgm_ops);

-- Comments for documentation
COMMENT ON TABLE vcons IS 'Main vCon container table - compliant with draft-ietf-vcon-vcon-core-02 (v0.4.0)';
COMMENT ON COLUMN vcons.extensions IS 'List of vCon extensions used (Section 4.1.3)';
COMMENT ON COLUMN vcons.critical IS 'List of incompatible extensions that must be supported (Section 4.1.4); renamed from must_support in v0.4.0';

COMMENT ON TABLE parties IS 'Party objects from vCon parties array (Section 4.2)';
COMMENT ON COLUMN parties.uuid IS 'Unique identifier for participant across vCons (Section 4.2.12)';
COMMENT ON COLUMN parties.data_subject_id IS 'EXTENSION: Data subject identifier for privacy tracking';

COMMENT ON TABLE dialog IS 'Dialog objects from vCon dialog array (Section 4.3)';
COMMENT ON COLUMN dialog.type IS 'Dialog type: recording, text, transfer, or incomplete (Section 4.3.1)';

COMMENT ON TABLE attachments IS 'Attachment objects from vCon attachments array (Section 4.4)';

COMMENT ON TABLE analysis IS 'Analysis objects from vCon analysis array (Section 4.5)';
COMMENT ON COLUMN analysis.vendor IS 'REQUIRED: Vendor/product name of analysis software (Section 4.5.5)';
COMMENT ON COLUMN analysis.schema IS 'Schema/format identifier for analysis data (Section 4.5.7)';
COMMENT ON COLUMN analysis.body IS 'Analysis content as string - supports JSON and non-JSON formats (Section 4.5.8)';

COMMENT ON TABLE groups IS 'Group objects for aggregated vCons (Section 4.6)';

COMMENT ON TABLE privacy_requests IS 'EXTENSION: Privacy request tracking (not in core vCon spec)';

-- Row Level Security (RLS) policies
ALTER TABLE vcons ENABLE ROW LEVEL SECURITY;
ALTER TABLE parties ENABLE ROW LEVEL SECURITY;
ALTER TABLE dialog ENABLE ROW LEVEL SECURITY;
ALTER TABLE attachments ENABLE ROW LEVEL SECURITY;
ALTER TABLE analysis ENABLE ROW LEVEL SECURITY;

-- Example RLS policy (adjust based on your auth setup)
CREATE POLICY vcons_isolation ON vcons
    USING (auth.uid()::text = processed_by);

-- Triggers for updated_at
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
    NEW.updated_at = NOW();
    RETURN NEW;
END;
$$ language 'plpgsql';

CREATE TRIGGER update_vcons_updated_at BEFORE UPDATE ON vcons
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();

CREATE TRIGGER update_privacy_requests_updated_at BEFORE UPDATE ON privacy_requests
    FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
```

## Migration from Original Schema

```sql
-- Migration script to update existing database to corrected schema
BEGIN;

-- 1. Add new required columns
ALTER TABLE vcons ADD COLUMN IF NOT EXISTS extensions TEXT[];
ALTER TABLE vcons ADD COLUMN IF NOT EXISTS critical TEXT[];
ALTER TABLE vcons ADD COLUMN IF NOT EXISTS amended JSONB DEFAULT '{}';
ALTER TABLE vcons ALTER COLUMN vcon_version SET DEFAULT '0.4.0';

ALTER TABLE parties ADD COLUMN IF NOT EXISTS did TEXT;
ALTER TABLE parties ADD COLUMN IF NOT EXISTS uuid UUID;

ALTER TABLE dialog ADD COLUMN IF NOT EXISTS session_id TEXT;
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS application TEXT;
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS message_id TEXT;

-- Add dialog_indices to analysis
ALTER TABLE analysis ADD COLUMN IF NOT EXISTS dialog_indices INTEGER[];

-- 2. Rename schema_version to schema
ALTER TABLE analysis RENAME COLUMN schema_version TO schema;

-- 3. Fix body field in analysis (most complex migration)
-- Create temp column
ALTER TABLE analysis ADD COLUMN body_new TEXT;

-- Convert existing JSONB to text
UPDATE analysis SET body_new = body::text WHERE body IS NOT NULL;

-- Drop old column and rename
ALTER TABLE analysis DROP COLUMN body;
ALTER TABLE analysis RENAME COLUMN body_new TO body;

-- 4. Make vendor required (set default first for existing rows)
UPDATE analysis SET vendor = 'unknown' WHERE vendor IS NULL OR vendor = '';
ALTER TABLE analysis ALTER COLUMN vendor SET NOT NULL;

-- 5. Remove encoding defaults
ALTER TABLE analysis ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE dialog ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE attachments ALTER COLUMN encoding DROP DEFAULT;

-- 6. Add constraints
ALTER TABLE dialog ADD CONSTRAINT IF NOT EXISTS dialog_type_check 
    CHECK (type IN ('recording', 'text', 'transfer', 'incomplete'));

ALTER TABLE dialog ADD CONSTRAINT IF NOT EXISTS dialog_encoding_check 
    CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

ALTER TABLE attachments ADD CONSTRAINT IF NOT EXISTS attachments_encoding_check 
    CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

ALTER TABLE analysis ADD CONSTRAINT IF NOT EXISTS analysis_encoding_check 
    CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

ALTER TABLE dialog ADD CONSTRAINT IF NOT EXISTS dialog_disposition_check 
    CHECK (disposition IS NULL OR disposition IN ('no-answer', 'congestion', 'failed', 'busy', 'hung-up', 'voicemail-no-message'));

-- 7. Create new tables
CREATE TABLE IF NOT EXISTS party_history (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    dialog_id UUID NOT NULL REFERENCES dialog(id) ON DELETE CASCADE,
    party_index INTEGER NOT NULL,
    time TIMESTAMPTZ NOT NULL,
    event TEXT NOT NULL CHECK (event IN ('join', 'drop', 'hold', 'unhold', 'mute', 'unmute'))
);

CREATE TABLE IF NOT EXISTS groups (
    id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
    vcon_id UUID NOT NULL REFERENCES vcons(id) ON DELETE CASCADE,
    group_index INTEGER NOT NULL,
    uuid UUID,
    body TEXT,
    encoding TEXT CHECK (encoding = 'json'),
    url TEXT,
    content_hash TEXT,
    UNIQUE(vcon_id, group_index)
);

-- 8. Create new indexes
CREATE INDEX IF NOT EXISTS idx_parties_uuid ON parties(uuid) WHERE uuid IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_dialog_session ON dialog(session_id) WHERE session_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_attachments_dialog ON attachments(dialog);
CREATE INDEX IF NOT EXISTS idx_analysis_schema ON analysis(schema) WHERE schema IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_analysis_dialog ON analysis USING GIN (dialog_indices);
CREATE INDEX IF NOT EXISTS idx_groups_vcon ON groups(vcon_id);
CREATE INDEX IF NOT EXISTS idx_groups_uuid ON groups(uuid) WHERE uuid IS NOT NULL;

-- 9. Update comments
COMMENT ON TABLE vcons IS 'Main vCon container table - compliant with draft-ietf-vcon-vcon-core-00';
COMMENT ON COLUMN analysis.schema IS 'Schema/format identifier for analysis data (Section 4.5.7)';
COMMENT ON COLUMN analysis.body IS 'Analysis content as string - supports JSON and non-JSON formats (Section 4.5.8)';

COMMIT;
```

## Verification Queries

```sql
-- Verify schema compliance

-- 1. Check for analysis without required vendor
SELECT COUNT(*) as missing_vendor FROM analysis WHERE vendor IS NULL OR vendor = '';
-- Should return 0

-- 2. Check dialog types are valid
SELECT DISTINCT type FROM dialog WHERE type NOT IN ('recording', 'text', 'transfer', 'incomplete');
-- Should return no rows

-- 3. Check encoding values are valid
SELECT 'dialog' as table_name, COUNT(*) as invalid_count 
FROM dialog WHERE encoding NOT IN ('base64url', 'json', 'none') AND encoding IS NOT NULL
UNION ALL
SELECT 'attachments', COUNT(*) 
FROM attachments WHERE encoding NOT IN ('base64url', 'json', 'none') AND encoding IS NOT NULL
UNION ALL
SELECT 'analysis', COUNT(*) 
FROM analysis WHERE encoding NOT IN ('base64url', 'json', 'none') AND encoding IS NOT NULL;
-- All counts should be 0

-- 4. Check schema field renamed
SELECT column_name FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name LIKE '%schema%';
-- Should show 'schema', not 'schema_version'

-- 5. Check body is TEXT type
SELECT data_type FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name = 'body';
-- Should return 'text', not 'jsonb'
```


# Implementation Corrections

## Executive Summary

This document identifies and corrects inconsistencies between the IETF vCon specification (draft-ietf-vcon-vcon-core-02, v0.4.0) and the MCP Server implementation specification. These corrections are critical for ensuring compliance with the vCon standard and interoperability with other vCon implementations.

## Critical Inconsistencies Found

### 1. Analysis Object Schema Field Naming

**Issue**: Field name mismatch between spec and implementation

**IETF Specification (Section 4.5.7)**:

```
schema: "String" (optional)
```

**Current Implementation**:

* Database schema uses: `schema_version TEXT`
* Tool definitions use: `schema_version`
* Type definitions use: `schema_version`

**Impact**:

* Non-compliant vCons will be created
* Interoperability failures with other vCon systems
* Database queries will fail to find analysis by schema

**Correction Required**:

```sql
-- Database Schema Change
ALTER TABLE analysis RENAME COLUMN schema_version TO schema;
```

```typescript
// Tool Definition Correction
interface AddAnalysisTool {
  name: "add_analysis";
  inputSchema: {
    properties: {
      analysis: {
        properties: {
          schema: { type: "string" },  // NOT schema_version
          // ...
        }
      }
    }
  }
}
```

***

### 2. Analysis Vendor Field Requirement

**Issue**: Vendor field optionality differs from specification

**IETF Specification (Section 4.5.5)**:

```
vendor: "String"  (REQUIRED - not optional)
```

**Current Implementation**:

* Database schema: `vendor TEXT` (nullable)
* Tool definitions mark vendor as optional

**Impact**:

* vCons may be created without required vendor information
* Non-compliant with IETF specification

**Correction Required**:

```sql
-- Database Schema Change
ALTER TABLE analysis ALTER COLUMN vendor SET NOT NULL;
```

```typescript
// Tool Definition Correction
interface AddAnalysisTool {
  inputSchema: {
    properties: {
      analysis: {
        properties: {
          vendor: { type: "string" },  // REQUIRED
        },
        required: ["type", "vendor", "body"]  // vendor is required
      }
    }
  }
}
```

***

### 3. Analysis Body Field Data Type

**Issue**: Body field storage type incompatible with specification

**IETF Specification (Section 4.5.8)**:

```
body: "String"
```

The body should be able to store ANY string content, including non-JSON formats.

**Current Implementation**:

```sql
body JSONB NOT NULL DEFAULT '{}'
```

**Impact**:

* Cannot store non-JSON analysis bodies (CSV, plain text, XML, etc.)
* Forces all analysis to be JSON format
* Data loss when storing non-JSON analysis results

**Correction Required**:

```sql
-- Database Schema Change
ALTER TABLE analysis ALTER COLUMN body TYPE TEXT;
ALTER TABLE analysis ALTER COLUMN body DROP DEFAULT;

-- Add a new field to track if body is JSON or needs encoding
ALTER TABLE analysis ADD COLUMN body_format TEXT DEFAULT 'json';
```

**Migration Strategy**:

```sql
-- For existing data
UPDATE analysis 
SET body = body::text,
    body_format = 'json'
WHERE body IS NOT NULL;
```

***

### 4. Encoding Field Default Values

**Issue**: Inconsistent default values for encoding across objects

**IETF Specification (Section 2.3.2)**:

```
encoding: "String"
Must be one of: "base64url", "json", "none"
```

**Current Implementation**:

* Analysis table: `encoding TEXT DEFAULT 'json'`
* Dialog table: `encoding TEXT DEFAULT 'none'`
* Attachments table: `encoding TEXT DEFAULT 'none'`

**Impact**:

* Inconsistent behavior across different object types
* Default assumptions may not match actual content

**Correction Required**:

```sql
-- Remove defaults, require explicit encoding specification
ALTER TABLE analysis ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE dialog ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE attachments ALTER COLUMN encoding DROP DEFAULT;

-- Add constraint to ensure valid values
ALTER TABLE analysis ADD CONSTRAINT analysis_encoding_check 
  CHECK (encoding IN ('base64url', 'json', 'none'));
ALTER TABLE dialog ADD CONSTRAINT dialog_encoding_check 
  CHECK (encoding IN ('base64url', 'json', 'none'));
ALTER TABLE attachments ADD CONSTRAINT attachments_encoding_check 
  CHECK (encoding IN ('base64url', 'json', 'none'));
```

***

### 5. Missing Dialog Type Values

**Issue**: Database doesn't enforce valid dialog types

**IETF Specification (Section 4.3.1)**:

```
type: "String"
Must be: "recording", "text", "transfer", or "incomplete"
```

**Current Implementation**:

```sql
type TEXT NOT NULL  -- No constraint
```

**Correction Required**:

```sql
ALTER TABLE dialog ADD CONSTRAINT dialog_type_check 
  CHECK (type IN ('recording', 'text', 'transfer', 'incomplete'));
```

***

### 6. Party UUID vs Data Subject ID

**Issue**: Mixing of party identification fields

**IETF Specification (Section 4.2.12)**:

```
uuid: "String" (optional)
The uuid is a unique identifier for the participant
```

**Current Implementation**:

* parties table has: `data_subject_id TEXT`
* Missing: `uuid` field from Party Object

**Impact**:

* Non-compliant party identification
* Cannot properly track parties across vCons per spec

**Correction Required**:

```sql
-- Add uuid field to parties table
ALTER TABLE parties ADD COLUMN uuid UUID;

-- data_subject_id is custom extension, not in spec
-- Keep for privacy tracking but add proper uuid field
CREATE INDEX idx_parties_uuid ON parties(uuid);
```

***

### 7. Analysis Dialog Reference

**Issue**: Missing proper dialog reference in analysis table

**IETF Specification (Section 4.5.2)**:

```
dialog: "UnsignedInt" | "UnsignedInt[]" (optional)
The index to dialog(s) this analysis was based upon
```

**Current Implementation**:

* No dedicated dialog reference field in analysis table

**Correction Required**:

```sql
-- Add dialog reference field
ALTER TABLE analysis ADD COLUMN dialog_indices INTEGER[];

-- Add index for querying analysis by dialog
CREATE INDEX idx_analysis_dialog ON analysis USING GIN (dialog_indices);
```

***

## Additional Recommendations

### 1. Standardize Parameter Names

The implementation uses both snake\_case and camelCase inconsistently. The IETF spec uses snake\_case throughout.

**Recommendation**: Use snake\_case for all parameter names to match IETF specification.

### 2. Add Type System Validation

**Recommendation**: Implement TypeScript types that exactly match IETF specification:

```typescript
// Exact type from IETF spec
type VConEncoding = 'base64url' | 'json' | 'none';
type DialogType = 'recording' | 'text' | 'transfer' | 'incomplete';

interface AnalysisObject {
  type: string;
  dialog?: number | number[];
  mediatype?: string;
  filename?: string;
  vendor: string;  // REQUIRED
  product?: string;
  schema?: string;  // NOT schema_version
  body?: string;
  encoding?: VConEncoding;
  url?: string;
  content_hash?: string | string[];
}
```

### 3. Separate Extension Fields from Core Fields

The implementation mixes vCon extension fields (like `data_subject_id`, consent tracking) with core vCon fields. These should be clearly separated.

**Recommendation**:

* Keep core vCon fields in main tables
* Create separate extension tables for privacy/consent tracking
* Document which fields are extensions vs. core spec

### 4. Tag Storage and Search

Per `vcon-dev/vcon-lib`, tags are represented as a dedicated attachment rather than a top-level column:

* Attachment with `type="tags"`, `encoding="json"`
* `body` is an array of strings like `"key:value"`

Search should derive tag filters by parsing this attachment (e.g., in SQL using `jsonb_array_elements_text`), or via a `vcon_tags_mv` materialized view with a GIN index on the aggregated JSONB object for performance.

***

## Implementation Priority

### High Priority (Breaking Changes)

1. Fix `schema_version` → `schema` field name
2. Make `vendor` field required in analysis
3. Change `body` from JSONB to TEXT in analysis table
4. Add proper `uuid` field to parties table

### Medium Priority (Data Quality)

5. Remove default values from encoding fields
6. Add dialog type constraints
7. Add dialog reference to analysis table

### Low Priority (Best Practices)

8. Standardize naming conventions
9. Add type system validation
10. Separate extension fields

***

## Migration Script

```sql
-- BEGIN TRANSACTION
BEGIN;

-- 1. Fix schema_version → schema
ALTER TABLE analysis RENAME COLUMN schema_version TO schema;

-- 2. Make vendor required (handle existing nulls first)
UPDATE analysis SET vendor = 'unknown' WHERE vendor IS NULL;
ALTER TABLE analysis ALTER COLUMN vendor SET NOT NULL;

-- 3. Fix body field type
-- First, convert existing JSONB to text
ALTER TABLE analysis ADD COLUMN body_text TEXT;
UPDATE analysis SET body_text = body::text WHERE body IS NOT NULL;
ALTER TABLE analysis DROP COLUMN body;
ALTER TABLE analysis RENAME COLUMN body_text TO body;

-- 4. Add uuid to parties
ALTER TABLE parties ADD COLUMN uuid UUID;

-- 5. Remove encoding defaults
ALTER TABLE analysis ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE dialog ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE attachments ALTER COLUMN encoding DROP DEFAULT;

-- 6. Add type constraints
ALTER TABLE dialog ADD CONSTRAINT dialog_type_check 
  CHECK (type IN ('recording', 'text', 'transfer', 'incomplete'));

ALTER TABLE analysis ADD CONSTRAINT analysis_encoding_check 
  CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

-- 7. Add dialog reference to analysis
ALTER TABLE analysis ADD COLUMN dialog_indices INTEGER[];
CREATE INDEX idx_analysis_dialog ON analysis USING GIN (dialog_indices);

-- 8. Add indexes
CREATE INDEX idx_parties_uuid ON parties(uuid) WHERE uuid IS NOT NULL;

COMMIT;
```

***

## Testing Checklist

After applying corrections:

* [ ] Create vCon with analysis object using `schema` field
* [ ] Verify `vendor` field is required in analysis
* [ ] Test storing non-JSON analysis body (CSV, plain text)
* [ ] Verify encoding field accepts "base64url", "json", "none"
* [ ] Test dialog type constraint accepts only valid types
* [ ] Create party with uuid field
* [ ] Test analysis with dialog\_indices array reference
* [ ] Export vCon and validate against IETF schema validator
* [ ] Test interoperability with other vCon implementations

***

## Documentation Updates Required

1. Update all tool definitions to use corrected field names
2. Update database schema documentation
3. Update API documentation
4. Create vCon compliance checklist
5. Add migration guide for existing deployments

***

## References

* IETF vCon Specification: draft-ietf-vcon-vcon-core-02.txt (v0.4.0)
* Original Implementation: MCP Server for IETF vCon with Supabase - Complete Implementation Specification.md
* Related: vcon\_adapter\_guide.md

***

## Questions for Resolution

1. Should we support both `schema` and `schema_version` for backwards compatibility?
2. How should we handle existing vCons with non-compliant field names?
3. Should the migration be applied automatically or require manual intervention?
4. What is the deprecation timeline for non-compliant fields?

***

*Document Version: 1.0*\
*Date: 2025-10-07*\
*Status: Draft for Review*


# Migration Guide

## Overview

This guide helps you migrate existing vCon implementation code to be spec-compliant. Use the search-and-replace patterns below to quickly fix common issues.

***

## 🔧 Search and Replace Patterns

### Pattern 1: Fix schema\_version → schema

**TypeScript/JavaScript Files:**

```bash
# Search for
schema_version

# Replace with
schema
```

**Files to update:**

* `src/types/vcon.ts`
* `src/tools/*.ts`
* `src/db/queries.ts`
* Any interface definitions
* Any object literals

**Example changes:**

```typescript
// Before
interface Analysis {
  schema_version?: string;
}

// After
interface Analysis {
  schema?: string;
}

// Before
const analysis = {
  type: 'test',
  schema_version: '1.0'
};

// After
const analysis = {
  type: 'test',
  schema: '1.0'
};
```

***

### Pattern 2: Make vendor required

**Find optional vendor:**

```typescript
// Search for
vendor?: string

// Replace with
vendor: string
```

**Update tool schemas:**

```typescript
// Before
properties: {
  vendor: { type: 'string' }
}

// After
properties: {
  vendor: { type: 'string' }
},
required: ['type', 'vendor']  // Add vendor to required array
```

***

### Pattern 3: Fix body type

**TypeScript files:**

```typescript
// Search for
body: object
// OR
body: any
// OR
body: JSONB

// Replace with
body?: string
```

**Database queries:**

```sql
-- Search for
body JSONB

-- Replace with
body TEXT
```

***

### Pattern 4: Add missing Party fields

**TypeScript interfaces:**

```typescript
// Search for
interface Party {
  tel?: string;
  sip?: string;
  mailto?: string;
  name?: string;
  // ... existing fields

// Replace with (add these fields)
interface Party {
  tel?: string;
  sip?: string;
  mailto?: string;
  name?: string;
  did?: string;          // ADD THIS
  uuid?: string;         // ADD THIS
  // ... existing fields
```

**Database schema:**

```sql
-- Add these columns if missing
ALTER TABLE parties ADD COLUMN IF NOT EXISTS did TEXT;
ALTER TABLE parties ADD COLUMN IF NOT EXISTS uuid UUID;
```

***

### Pattern 5: Add missing Dialog fields

**TypeScript interfaces:**

```typescript
// Add to Dialog interface if missing
interface Dialog {
  // ... existing fields
  session_id?: string;     // ADD
  application?: string;    // ADD
  message_id?: string;     // ADD
  // ... existing fields
}
```

**Database schema:**

```sql
-- Add these columns if missing
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS session_id TEXT;
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS application TEXT;
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS message_id TEXT;
```

***

### Pattern 6: Remove encoding defaults

**Database schema:**

```sql
-- Search for
encoding TEXT DEFAULT 'json'
encoding TEXT DEFAULT 'none'

-- Replace with
encoding TEXT CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'))
```

**Migration SQL:**

```sql
ALTER TABLE analysis ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE dialog ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE attachments ALTER COLUMN encoding DROP DEFAULT;
```

***

### Pattern 7: Add dialog\_indices to Analysis

**TypeScript interface:**

```typescript
// Add to Analysis interface
interface Analysis {
  type: string;
  dialog?: number | number[];  // ADD THIS if missing
  // ... other fields
}
```

**Database:**

```sql
-- Add column if missing
ALTER TABLE analysis ADD COLUMN IF NOT EXISTS dialog_indices INTEGER[];
```

***

## 🔄 Complete Migration Script

Run this bash script to automatically fix most issues:

```bash
#!/bin/bash
# fix-vcon-compliance.sh

echo "🔧 Fixing vCon Spec Compliance Issues..."

# Fix schema_version → schema in TypeScript/JavaScript
echo "📝 Fixing schema_version → schema..."
find src -type f \( -name "*.ts" -o -name "*.js" \) -exec sed -i '' 's/schema_version/schema/g' {} +

# Fix optional vendor in interfaces
echo "📝 Making vendor required..."
find src/types -type f -name "*.ts" -exec sed -i '' 's/vendor?: string/vendor: string/g' {} +

# Fix body type
echo "📝 Fixing body type..."
find src/types -type f -name "*.ts" -exec sed -i '' 's/body: object/body?: string/g' {} +
find src/types -type f -name "*.ts" -exec sed -i '' 's/body: any/body?: string/g' {} +

# Add TODO comments for manual fixes
echo "📝 Adding TODO comments for manual review..."
find src -type f \( -name "*.ts" -o -name "*.js" \) -exec sed -i '' 's/interface Party {/interface Party {\n  \/\/ TODO: Add uuid?: string; and did?: string; if missing/g' {} +
find src -type f \( -name "*.ts" -o -name "*.js" \) -exec sed -i '' 's/interface Dialog {/interface Dialog {\n  \/\/ TODO: Add session_id?: string; application?: string; message_id?: string; if missing/g' {} +

echo "✅ Automated fixes complete!"
echo ""
echo "⚠️  Manual review required for:"
echo "  1. Check all TODO comments added"
echo "  2. Update tool schemas to require vendor"
echo "  3. Update database schema (run migration SQL)"
echo "  4. Add missing interface fields"
echo ""
echo "📋 Run verification:"
echo "  npm run test:compliance"
```

**Make it executable:**

```bash
chmod +x fix-vcon-compliance.sh
./fix-vcon-compliance.sh
```

***

## 📊 Database Migration

Complete database migration in order:

```sql
-- Step 1: Rename columns
BEGIN;

ALTER TABLE analysis RENAME COLUMN schema_version TO schema;

COMMIT;

-- Step 2: Add missing columns
BEGIN;

-- Add to parties
ALTER TABLE parties ADD COLUMN IF NOT EXISTS did TEXT;
ALTER TABLE parties ADD COLUMN IF NOT EXISTS uuid UUID;

-- Add to dialog  
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS session_id TEXT;
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS application TEXT;
ALTER TABLE dialog ADD COLUMN IF NOT EXISTS message_id TEXT;

-- Add to analysis
ALTER TABLE analysis ADD COLUMN IF NOT EXISTS dialog_indices INTEGER[];

-- Add to vcons
ALTER TABLE vcons ADD COLUMN IF NOT EXISTS extensions TEXT[];
ALTER TABLE vcons ADD COLUMN IF NOT EXISTS must_support TEXT[];

COMMIT;

-- Step 3: Fix body type
BEGIN;

ALTER TABLE analysis ADD COLUMN body_new TEXT;
UPDATE analysis SET body_new = body::text WHERE body IS NOT NULL;
ALTER TABLE analysis DROP COLUMN body;
ALTER TABLE analysis RENAME COLUMN body_new TO body;

COMMIT;

-- Step 4: Make vendor required
BEGIN;

-- Set default for existing nulls
UPDATE analysis SET vendor = 'unknown' WHERE vendor IS NULL OR vendor = '';

-- Make required
ALTER TABLE analysis ALTER COLUMN vendor SET NOT NULL;

COMMIT;

-- Step 5: Remove defaults and add constraints
BEGIN;

-- Remove defaults
ALTER TABLE analysis ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE dialog ALTER COLUMN encoding DROP DEFAULT;
ALTER TABLE attachments ALTER COLUMN encoding DROP DEFAULT;

-- Add constraints
ALTER TABLE dialog ADD CONSTRAINT dialog_type_check 
  CHECK (type IN ('recording', 'text', 'transfer', 'incomplete'));

ALTER TABLE dialog ADD CONSTRAINT dialog_encoding_check 
  CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

ALTER TABLE attachments ADD CONSTRAINT attachments_encoding_check 
  CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

ALTER TABLE analysis ADD CONSTRAINT analysis_encoding_check 
  CHECK (encoding IS NULL OR encoding IN ('base64url', 'json', 'none'));

COMMIT;

-- Step 6: Create indexes
BEGIN;

CREATE INDEX IF NOT EXISTS idx_parties_uuid ON parties(uuid) WHERE uuid IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_dialog_session ON dialog(session_id) WHERE session_id IS NOT NULL;
CREATE INDEX IF NOT EXISTS idx_analysis_dialog ON analysis USING GIN (dialog_indices);

COMMIT;
```

**Verification queries:**

```sql
-- Verify schema column renamed
SELECT column_name FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name = 'schema';
-- Should return 1 row

-- Verify no schema_version
SELECT column_name FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name = 'schema_version';
-- Should return 0 rows

-- Verify vendor is required
SELECT is_nullable FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name = 'vendor';
-- Should return 'NO'

-- Verify body is TEXT
SELECT data_type FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name = 'body';
-- Should return 'text'

-- Verify no defaults on encoding
SELECT column_default FROM information_schema.columns 
WHERE table_name = 'analysis' AND column_name = 'encoding';
-- Should return NULL

-- Verify constraints exist
SELECT constraint_name FROM information_schema.table_constraints 
WHERE table_name = 'dialog' AND constraint_name = 'dialog_type_check';
-- Should return 1 row
```

***

## 🧪 Testing After Migration

### 1. TypeScript Compilation

```bash
# Should compile without errors
npm run build

# If errors, check:
# - All schema_version changed to schema
# - All vendor fields not optional in Analysis type
# - All body fields are string type
```

### 2. Compliance Tests

```bash
# Run compliance tests
npm run test:compliance

# All tests should pass
# If failures, check error messages for specific issues
```

### 3. Database Verification

```bash
# Run verification queries from CORRECTED_SCHEMA.md
psql -d your_database -f verify-schema.sql

# All queries should return expected results
```

### 4. Manual Code Review

```bash
# Search for any remaining issues

# 1. Check for schema_version
grep -r "schema_version" src/
# Should return 0 results

# 2. Check for optional vendor in Analysis
grep -A5 "interface Analysis" src/types/vcon.ts | grep "vendor?"
# Should return 0 results

# 3. Check for object/any body types
grep -A20 "interface Analysis" src/types/vcon.ts | grep "body.*object\|body.*any"
# Should return 0 results

# 4. Check database queries use correct fields
grep -r "schema_version" src/db/
# Should return 0 results
```

***

## 📝 Manual Review Checklist

After running automated fixes:

### TypeScript Types (`src/types/vcon.ts`)

* [ ] `schema` not `schema_version` in Analysis
* [ ] `vendor: string` (required) in Analysis
* [ ] `body?: string` in Analysis
* [ ] `uuid?: string` in Party
* [ ] `did?: string` in Party
* [ ] `session_id?: string` in Dialog
* [ ] `application?: string` in Dialog
* [ ] `message_id?: string` in Dialog
* [ ] `extensions?: string[]` in VCon
* [ ] `must_support?: string[]` in VCon

### Tool Definitions (`src/tools/*.ts`)

* [ ] All tools use `schema` not `schema_version`
* [ ] addAnalysisTool requires vendor field
* [ ] Tool schemas use correct types

### Database Queries (`src/db/queries.ts`)

* [ ] All queries use `schema` column name
* [ ] All INSERT for analysis include vendor
* [ ] All SELECT retrieve new fields

### Database Schema

* [ ] Run migration SQL successfully
* [ ] All verification queries pass
* [ ] Constraints are in place

***

## 🚨 Rollback Plan

If migration fails:

```sql
-- Create backup before migration
pg_dump your_database > backup_before_vcon_migration.sql

-- If needed, restore
psql your_database < backup_before_vcon_migration.sql

-- For code, use git
git checkout HEAD -- .
```

***

## 📞 Support

If you encounter issues:

1. Check `IMPLEMENTATION_CORRECTIONS.md` for detailed explanations
2. Review `CLAUDE.md` for correct implementations
3. Consult IETF spec: `background_docs/draft-ietf-vcon-vcon-core-00.txt`
4. Run compliance tests to identify specific failures

***

*Last Updated: April 2026*\
*For use with: draft-ietf-vcon-vcon-core-02 (v0.4.0)*


# Quick Reference

## ⚠️ STOP! Read This Before Implementing

This checklist ensures you use the CORRECT field names per IETF spec.

***

## 🔴 CRITICAL CORRECTIONS

### Analysis Object

```typescript
// ❌ WRONG - DO NOT USE
interface AnalysisWrong {
  schema_version?: string;  // WRONG NAME
  vendor?: string;          // WRONG - NOT OPTIONAL
  body: any;                // WRONG TYPE
}

// ✅ CORRECT - USE THIS
interface Analysis {
  type: string;
  vendor: string;           // REQUIRED ✓
  schema?: string;          // CORRECT NAME ✓
  body?: string;            // CORRECT TYPE ✓
}
```

**Database:**

```sql
-- ❌ WRONG
schema_version TEXT
vendor TEXT  -- nullable
body JSONB

-- ✅ CORRECT
schema TEXT
vendor TEXT NOT NULL
body TEXT
```

***

### Party Object

```typescript
// ❌ MISSING
interface PartyWrong {
  tel?: string;
  name?: string;
  // missing uuid field
}

// ✅ CORRECT
interface Party {
  tel?: string;
  name?: string;
  uuid?: string;  // ADD THIS ✓
}
```

***

### Dialog Object

```typescript
// ❌ MISSING FIELDS
interface DialogWrong {
  type: string;
  start?: string;
  // missing session_id, application, message_id
}

// ✅ CORRECT
interface Dialog {
  type: 'recording' | 'text' | 'transfer' | 'incomplete';
  start?: string;
  session_id?: { local: string; remote: string };  // Object in v0.4.0 ✓
  application?: string;     // ADD THIS ✓
  message_id?: string;      // ADD THIS ✓
}
```

***

### Tags (Search)

Tags are stored as a special attachment within the vCon:

* `type: "tags"`
* `encoding: "json"`
* `body: ["key:value", ...]`

Search RPCs (`search_vcons_keyword`, `search_vcons_semantic`, `search_vcons_hybrid`) parse tags from attachments for filtering.

***

### Encoding Fields

```typescript
// ❌ WRONG - Has default
encoding TEXT DEFAULT 'json'

// ✅ CORRECT - No default
encoding TEXT CHECK (encoding IN ('base64url', 'json', 'none'))
```

***

## 📋 Pre-Implementation Checklist

Before writing ANY code:

* [ ] I have read `CLAUDE.md`
* [ ] I have read `IMPLEMENTATION_CORRECTIONS.md`
* [ ] I understand `schema` NOT `schema_version`
* [ ] I understand `vendor` is REQUIRED in analysis
* [ ] I understand `body` must be TEXT/string
* [ ] I understand NO default values for `encoding`

***

## 🔍 Code Review Checklist

Before committing:

### TypeScript Types

* [ ] No references to `schema_version` anywhere
* [ ] Analysis.vendor is not optional (no `?`)
* [ ] Analysis.body is `string` type, not `object` or `any`
* [ ] Party has `uuid?: string` field
* [ ] Dialog has `session_id`, `application`, `message_id` fields
* [ ] VCon has `extensions?: string[]` and `critical?: string[]` (renamed from `must_support` in v0.4.0)

### Database Schema

* [ ] analysis table has `schema` column (not `schema_version`)
* [ ] analysis.vendor is NOT NULL
* [ ] analysis.body is TEXT (not JSONB)
* [ ] No DEFAULT on encoding columns
* [ ] dialog.type has CHECK constraint
* [ ] parties table has uuid column
* [ ] analysis table has dialog\_indices column

### Tool Definitions

* [ ] addAnalysisTool requires `vendor` in schema
* [ ] addAnalysisTool uses `schema` (not `schema_version`)
* [ ] All tool schemas use correct field names

### Queries

* [ ] Database queries reference `schema` not `schema_version`
* [ ] INSERT statements include vendor as required
* [ ] SELECT statements include all new fields

***

## 🚨 Common Mistakes

### Mistake #1: Using schema\_version

```typescript
// ❌ WRONG
const analysis = {
  type: 'transcript',
  schema_version: '1.0'  // WRONG FIELD NAME
};

// ✅ CORRECT
const analysis = {
  type: 'transcript',
  schema: '1.0'  // CORRECT
};
```

### Mistake #2: Making vendor optional

```typescript
// ❌ WRONG
interface Analysis {
  vendor?: string;  // WRONG - should be required
}

// ✅ CORRECT
interface Analysis {
  vendor: string;  // REQUIRED - no ?
}
```

### Mistake #3: Using object for body

```typescript
// ❌ WRONG
interface Analysis {
  body?: object;  // WRONG TYPE
}

// ✅ CORRECT
interface Analysis {
  body?: string;  // Can contain JSON, CSV, XML, etc.
}
```

### Mistake #4: Forgetting new fields

```typescript
// ❌ MISSING FIELDS
interface Party {
  name?: string;
  tel?: string;
  // missing uuid, did
}

// ✅ CORRECT
interface Party {
  name?: string;
  tel?: string;
  uuid?: string;
  did?: string;
}
```

***

## 🧪 Quick Test

Run this test to verify compliance:

```typescript
import { Analysis, Party, Dialog, VCon } from './types/vcon';

// This should compile without errors
const analysis: Analysis = {
  type: 'test',
  vendor: 'TestVendor',  // Required field
  schema: '1.0',         // Correct field name
  body: 'any string',    // String type
  encoding: 'none'
};

// This should compile without errors
const party: Party = {
  name: 'Test',
  uuid: '123e4567-e89b-12d3-a456-426614174000'
};

// This should compile without errors
const dialog: Dialog = {
  type: 'recording',
  session_id: { local: 'session-local-123', remote: 'session-remote-123' },
  application: 'TestApp'
};

// This should NOT compile (schema_version doesn't exist)
const wrongAnalysis: Analysis = {
  type: 'test',
  vendor: 'Test',
  schema_version: '1.0'  // TypeScript error!
};

// This should NOT compile (vendor is required)
const wrongAnalysis2: Analysis = {
  type: 'test',
  // vendor: 'Test',  // Missing required field!
  body: 'test'
};
```

***

## 📚 Quick Links

* Full instructions: `CLAUDE.md`
* Detailed corrections: `IMPLEMENTATION_CORRECTIONS.md`
* Database schema: `CORRECTED_SCHEMA.md`
* IETF spec (in repo, v0.3.0 baseline): `background_docs/draft-ietf-vcon-vcon-core-00.txt`
* IETF spec (current draft -02 / v0.4.0): <https://datatracker.ietf.org/doc/draft-ietf-vcon-vcon-core/>

***

## ✅ Final Verification

After implementation, verify:

```bash
# 1. Check TypeScript compilation
npm run build
# Should have NO errors

# 2. Run compliance tests
npm run test:compliance
# Should PASS all tests

# 3. Verify database schema
psql -d your_db -f scripts/verify-schema.sql
# Should return 0 errors

# 4. Search for wrong field names
grep -r "schema_version" src/
# Should return NO results

grep -r "vendor\?" src/types/
# Should return NO results in Analysis type
```

***

## 🆘 If You're Unsure

**STOP and check:**

1. Is this field name in the IETF spec?
2. Is this field marked optional or required in spec?
3. What is the exact type in the spec?

**Then verify against:**

* `CLAUDE.md` - Section matching your task
* `IMPLEMENTATION_CORRECTIONS.md` - List of all corrections
* `background_docs/draft-ietf-vcon-vcon-core-00.txt` (in repo) — and the current `-02` draft on the IETF datatracker for the authoritative spec

***

*Last Updated: April 2026*\
*Spec Version: draft-ietf-vcon-vcon-core-02*\
*Schema Version: 0.4.0*


# Features

## Executive Summary

This document provides a comprehensive specification of ALL functionality that will be included in the **open source** vCon MCP server. The goal is to create a powerful, production-ready core that handles all non-privacy/non-compliance operations, making it valuable for general conversation data management.

***

## 1. Core vCon CRUD Operations

### 1.1 Create Operations

#### `create_vcon` Tool

Create a new vCon from JSON data with full validation.

**Input Schema:**

```typescript
{
  vcon_data: {
    type: "object";
    description: "Complete vCon JSON object following IETF spec";
    required: true;
  };
  metadata?: {
    type: "object";
    description: "Additional metadata (basename, filename, tags)";
  };
  validate_before_insert?: {
    type: "boolean";
    default: true;
    description: "Run validation before inserting";
  };
  return_created?: {
    type: "boolean";
    default: true;
    description: "Return the created vCon object";
  };
}
```

**Features:**

* Full IETF vCon specification compliance
* Automatic UUID generation if not provided
* Timestamp management (created\_at, updated\_at)
* Validation before insertion
* Support for all vCon components (parties, dialog, attachments, analysis)

#### `create_vcon_from_template` Tool

Create vCons from predefined templates.

**Input Schema:**

```typescript
{
  template_name: {
    type: "string";
    enum: ["phone_call", "chat_conversation", "email_thread", "video_meeting", "custom"];
  };
  parties: {
    type: "array";
    items: { /* Party schema */ };
    description: "Participants in the conversation";
  };
  subject?: {
    type: "string";
    description: "Conversation subject/title";
  };
  metadata?: {
    type: "object";
  };
}
```

**Features:**

* Pre-configured templates for common conversation types
* Smart defaults for different conversation mediums
* Extensible template system

### 1.2 Read Operations

#### `get_vcon` Tool

Retrieve a vCon by UUID.

**Input Schema:**

```typescript
{
  uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  include_components?: {
    type: "array";
    items: { type: "string"; enum: ["parties", "dialog", "attachments", "analysis", "all"] };
    default: ["all"];
  };
  include_metadata?: {
    type: "boolean";
    default: true;
  };
}
```

**Features:**

* Selective component retrieval
* Full object reconstruction from normalized schema
* Efficient querying with indexed lookups

#### `get_vcon_by_subject` Tool

Find vCons by subject text.

**Input Schema:**

```typescript
{
  subject: {
    type: "string";
    description: "Subject to search for (supports partial matching)";
  };
  exact_match?: {
    type: "boolean";
    default: false;
  };
  limit?: {
    type: "integer";
    default: 100;
    maximum: 1000;
  };
}
```

#### `list_vcons` Tool

List all vCons with pagination.

**Input Schema:**

```typescript
{
  limit?: {
    type: "integer";
    default: 100;
    maximum: 1000;
  };
  offset?: {
    type: "integer";
    default: 0;
  };
  sort_by?: {
    type: "string";
    enum: ["created_at", "updated_at", "subject"];
    default: "created_at";
  };
  sort_order?: {
    type: "string";
    enum: ["asc", "desc"];
    default: "desc";
  };
}
```

### 1.3 Update Operations

#### `update_vcon` Tool

Update vCon metadata and properties.

**Input Schema:**

```typescript
{
  uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  updates: {
    type: "object";
    description: "Fields to update";
    required: true;
  };
  merge_strategy?: {
    type: "string";
    enum: ["replace", "merge", "append"];
    default: "merge";
    description: "How to handle nested object updates";
  };
  validate_after_update?: {
    type: "boolean";
    default: true;
  };
}
```

**Features:**

* Subject updates
* Metadata updates
* Tag management
* Group data updates
* Redaction rules updates

#### `update_vcon_status` Tool

Update processing status flags.

**Input Schema:**

```typescript
{
  uuid: {
    type: "string";
    format: "uuid";
  };
  done?: {
    type: "boolean";
  };
  corrupt?: {
    type: "boolean";
  };
  processed_by?: {
    type: "string";
  };
}
```

### 1.4 Delete Operations

#### `delete_vcon` Tool

Delete a vCon and all related data.

**Input Schema:**

```typescript
{
  uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  confirm: {
    type: "boolean";
    required: true;
    description: "Confirmation flag to prevent accidental deletion";
  };
  cascade_delete?: {
    type: "boolean";
    default: true;
    description: "Delete all related parties, dialog, attachments, analysis";
  };
}
```

**Features:**

* Cascade deletion of all related components
* Confirmation requirement
* Transaction safety

#### `bulk_delete_vcons` Tool

Delete multiple vCons in a batch.

**Input Schema:**

```typescript
{
  uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
    required: true;
  };
  confirm: {
    type: "boolean";
    required: true;
  };
}
```

***

## 2. Component Management

### 2.1 Party Management

#### `add_party` Tool

Add a participant to a vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  party: {
    type: "object";
    properties: {
      name?: { type: "string" };
      tel?: { type: "string" };
      email?: { type: "string"; format: "email" };
      role?: { type: "string" };
      organization?: { type: "string" };
      uuid?: { type: "string"; format: "uuid" };
      metadata?: { type: "object" };
    };
    required: true;
  };
  return_index?: {
    type: "boolean";
    default: true;
    description: "Return the index of the newly added party";
  };
}
```

#### `update_party` Tool

Update party information.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  party_index: {
    type: "integer";
    minimum: 0;
    description: "Index of party in parties array";
  };
  updates: {
    type: "object";
    description: "Fields to update";
  };
}
```

#### `remove_party` Tool

Remove a party from a vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  party_index: {
    type: "integer";
    minimum: 0;
  };
  reindex_dialogs?: {
    type: "boolean";
    default: true;
    description: "Automatically update dialog party references";
  };
}
```

#### `find_party` Tool

Find parties matching criteria.

**Input Schema:**

```typescript
{
  vcon_uuid?: {
    type: "string";
    format: "uuid";
    description: "Search within specific vCon, or across all if omitted";
  };
  name?: { type: "string" };
  email?: { type: "string" };
  tel?: { type: "string" };
  role?: { type: "string" };
  organization?: { type: "string" };
}
```

### 2.2 Dialog Management

#### `add_dialog` Tool

Add dialog entry (recording, transcript, message).

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  dialog: {
    type: "object";
    properties: {
      type: { 
        type: "string"; 
        enum: ["recording", "text", "transfer", "video", "email"];
        required: true;
      };
      start: { 
        type: "string"; 
        format: "date-time";
        description: "ISO 8601 timestamp";
      };
      duration?: { 
        type: "number";
        description: "Duration in seconds";
      };
      parties: { 
        type: "array"; 
        items: { type: "integer" };
        description: "Array of party indices involved in this dialog";
      };
      originator?: { 
        type: "integer";
        description: "Party index of originator";
      };
      mimetype?: { type: "string" };
      filename?: { type: "string" };
      body?: { 
        type: "string";
        description: "Content (text or base64 encoded)";
      };
      encoding?: {
        type: "string";
        enum: ["none", "base64", "json"];
      };
      url?: {
        type: "string";
        format: "uri";
        description: "External URL for content";
      };
      disposition?: {
        type: "string";
        enum: ["render", "inline", "attachment"];
      };
      metadata?: { type: "object" };
    };
  };
}
```

**Features:**

* Support for all dialog types (text, audio, video, email)
* Inline or external content (URL)
* Base64 encoding for binary data
* Duration tracking
* Party and originator references

#### `update_dialog` Tool

Update dialog entry.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  dialog_index: {
    type: "integer";
    minimum: 0;
  };
  updates: {
    type: "object";
  };
}
```

#### `remove_dialog` Tool

Remove a dialog entry.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  dialog_index: {
    type: "integer";
    minimum: 0;
  };
}
```

#### `get_dialogs` Tool

Get all dialogs for a vCon with filtering.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  type?: {
    type: "string";
    enum: ["recording", "text", "transfer", "video", "email"];
  };
  party_index?: {
    type: "integer";
    description: "Filter by party involvement";
  };
  date_range?: {
    type: "object";
    properties: {
      start: { type: "string"; format: "date-time" };
      end: { type: "string"; format: "date-time" };
    };
  };
}
```

### 2.3 Attachment Management

#### `add_attachment` Tool

Add attachment to vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  attachment: {
    type: "object";
    properties: {
      type: { 
        type: "string";
        description: "Attachment type (custom types allowed)";
        required: true;
      };
      start?: { 
        type: "string"; 
        format: "date-time";
      };
      party?: {
        type: "integer";
        description: "Associated party index";
      };
      dialog?: {
        type: "integer";
        description: "Associated dialog index";
      };
      mimetype?: { type: "string" };
      filename?: { type: "string" };
      body: { 
        type: "string";
        description: "Attachment content";
        required: true;
      };
      encoding?: {
        type: "string";
        enum: ["none", "base64", "json"];
      };
      url?: {
        type: "string";
        format: "uri";
      };
    };
  };
}
```

**Features:**

* Custom attachment types
* Party and dialog associations
* Inline or external content
* MIME type support

#### `get_attachments` Tool

Retrieve attachments with filtering.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  type?: {
    type: "string";
    description: "Filter by attachment type";
  };
  party_index?: {
    type: "integer";
  };
  dialog_index?: {
    type: "integer";
  };
}
```

#### `update_attachment` Tool

Update attachment metadata.

#### `remove_attachment` Tool

Remove an attachment.

### 2.4 Analysis Management

#### `add_analysis` Tool

Add analysis result to vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  analysis: {
    type: "object";
    properties: {
      type: { 
        type: "string";
        description: "Analysis type (e.g., 'sentiment', 'summary', 'transcription')";
        required: true;
      };
      dialog?: {
        type: "integer";
        description: "Associated dialog index";
      };
      vendor?: { 
        type: "string";
        description: "Analysis vendor/tool name";
      };
      product?: { 
        type: "string";
        description: "Specific product/model used";
      };
      schema?: { 
        type: "string";
        description: "Schema version for analysis body";
      };
      body: { 
        type: "object";
        description: "Analysis result data";
        required: true;
      };
      encoding?: {
        type: "string";
        enum: ["json", "none"];
        default: "json";
      };
      confidence?: {
        type: "number";
        minimum: 0;
        maximum: 1;
        description: "Confidence score for analysis";
      };
    };
  };
}
```

**Features:**

* Flexible analysis types
* Vendor attribution
* Confidence scores
* Dialog association
* Structured result data

#### `get_analysis` Tool

Retrieve analysis results with filtering.

**Input Schema:**

```typescript
{
  vcon_uuid?: {
    type: "string";
    format: "uuid";
    description: "Specific vCon, or search across all";
  };
  analysis_type?: {
    type: "string";
    description: "Filter by analysis type";
  };
  vendor?: {
    type: "string";
  };
  min_confidence?: {
    type: "number";
    minimum: 0;
    maximum: 1;
  };
  dialog_index?: {
    type: "integer";
  };
}
```

#### `update_analysis` Tool

Update analysis result.

#### `remove_analysis` Tool

Remove an analysis result.

***

## 3. Search & Query Operations

### 3.1 Basic Search

#### `search_vcons` Tool

Advanced search across vCons.

**Input Schema:**

```typescript
{
  // Text search
  query?: {
    type: "string";
    description: "Full-text search query";
  };
  subject?: {
    type: "string";
    description: "Search by subject";
  };
  
  // Party search
  party_name?: { type: "string" };
  party_email?: { type: "string" };
  party_tel?: { type: "string" };
  party_role?: { type: "string" };
  
  // Dialog search
  dialog_type?: {
    type: "string";
    enum: ["recording", "text", "transfer", "video", "email"];
  };
  dialog_content?: {
    type: "string";
    description: "Search within dialog content";
  };
  
  // Analysis search
  analysis_type?: {
    type: "string";
    description: "Filter by analysis type";
  };
  
  // Metadata search
  tags?: {
    type: "object";
    description: "Search by tags (key-value pairs)";
  };
  
  // Date range
  date_range?: {
    type: "object";
    properties: {
      start: { type: "string"; format: "date-time" };
      end: { type: "string"; format: "date-time" };
    };
  };
  
  // Status filters
  done?: { type: "boolean" };
  corrupt?: { type: "boolean" };
  
  // Result options
  limit?: {
    type: "integer";
    default: 100;
    maximum: 1000;
  };
  offset?: {
    type: "integer";
    default: 0;
  };
  sort_by?: {
    type: "string";
    enum: ["created_at", "updated_at", "subject", "relevance"];
    default: "created_at";
  };
  sort_order?: {
    type: "string";
    enum: ["asc", "desc"];
    default: "desc";
  };
  
  // Component selection
  include_components?: {
    type: "array";
    items: { type: "string"; enum: ["parties", "dialog", "attachments", "analysis", "metadata"] };
    default: ["metadata"];
  };
}
```

**Features:**

* Full-text search across subjects and content
* Multi-field filtering
* Date range queries
* Party-based search
* Analysis type filtering
* Tag-based search
* Pagination support
* Configurable result components

### 3.2 Advanced Search

#### `full_text_search` Tool

PostgreSQL full-text search.

**Input Schema:**

```typescript
{
  search_query: {
    type: "string";
    description: "Search query using PostgreSQL syntax";
    required: true;
  };
  search_fields?: {
    type: "array";
    items: { type: "string"; enum: ["subject", "dialog_content", "analysis_content"] };
    default: ["subject", "dialog_content"];
  };
  rank_threshold?: {
    type: "number";
    default: 0.1;
    description: "Minimum relevance rank (0-1)";
  };
  limit?: { type: "integer"; default: 100 };
}
```

**Features:**

* PostgreSQL tsvector search
* Relevance ranking
* Multi-field search
* Configurable thresholds

#### `semantic_search` Tool

Vector-based semantic search for conversation content.

**Input Schema:**

```typescript
{
  query: {
    type: "string";
    required: true;
    description: "Natural language query describing what you're looking for";
  };
  search_scope?: {
    type: "array";
    items: { type: "string"; enum: ["subject", "dialog", "analysis_summaries"] };
    default: ["subject", "dialog"];
    description: "Where to perform semantic search";
  };
  similarity_threshold?: {
    type: "number";
    minimum: 0;
    maximum: 1;
    default: 0.7;
    description: "Minimum cosine similarity (0-1)";
  };
  embedding_provider?: {
    type: "string";
    enum: ["openai", "sentence_transformers", "custom"];
    default: "openai";
    description: "Embedding model provider";
  };
  limit?: {
    type: "integer";
    default: 20;
    maximum: 100;
  };
  include_similarity_scores?: {
    type: "boolean";
    default: true;
  };
  filter_tags?: {
    type: "object";
    description: "Pre-filter by exact tags before semantic search";
  };
}
```

**How It Works:**

1. Query is converted to vector embedding
2. Conversation content (subjects, dialog, summaries) are pre-embedded and stored
3. Cosine similarity computed between query and stored embeddings
4. Results ranked by semantic similarity

**Example Use Cases:**

```typescript
// Natural language search
semantic_search("customer frustrated about billing errors")
// Finds conversations about billing issues even if tagged differently
// Returns vCons discussing invoices, charges, payment problems

// Conceptual search
semantic_search("technical troubleshooting with escalation")
// Finds complex support conversations regardless of exact wording

// Intent-based search
semantic_search("customer wants to upgrade their subscription")
// Finds sales conversations about upsells, plan changes, expansions
```

**Response:**

```typescript
{
  results: Array<{
    vcon_uuid: string;
    similarity_score: number;
    matched_content: {
      subject?: string;
      dialog_excerpts?: Array<{
        dialog_index: number;
        text: string;
        relevance: number;
      }>;
    };
    tags?: object;
  }>;
  query_embedding?: number[]; // Optional: return for debugging
}
```

**Features:**

* Natural language queries
* Concept-based matching (not just keywords)
* Cross-lingual search (if model supports it)
* Intent and sentiment matching
* Can combine with tag filters for hybrid search

**Implementation Notes:**

* Requires embedding storage (vector column in PostgreSQL with pgvector extension)
* Embeddings can be pre-computed during vCon ingestion
* Can use OpenAI embeddings, Sentence Transformers, or custom models
* Consider caching embeddings for frequently searched content

#### `hybrid_search` Tool

Combine semantic and exact search for best results.

**Input Schema:**

```typescript
{
  semantic_query?: {
    type: "string";
    description: "Natural language query for semantic matching";
  };
  keyword_query?: {
    type: "string";
    description: "Keywords for exact/full-text matching";
  };
  tags?: {
    type: "object";
    description: "Exact tag filters";
  };
  weight_semantic?: {
    type: "number";
    minimum: 0;
    maximum: 1;
    default: 0.5;
    description: "Weight for semantic results (1 - this = keyword weight)";
  };
  limit?: {
    type: "integer";
    default: 20;
  };
}
```

**Example:**

```typescript
hybrid_search({
  semantic_query: "customer unhappy with service quality",
  tags: {
    department: "support",
    status: "open"
  },
  weight_semantic: 0.7
})
// Returns: Open support conversations semantically similar to
// "customer unhappy with service quality"
```

**Benefits of Hybrid Approach:**

1. **Precision + Recall**: Exact tags for precision, semantic for recall
2. **Handle Typos**: Semantic search doesn't require exact spelling
3. **Find Concepts**: Semantic finds related concepts not in tags
4. **Controllable**: Adjust weights based on use case

#### `aggregate_stats` Tool

Get aggregated statistics.

**Input Schema:**

```typescript
{
  group_by?: {
    type: "string";
    enum: ["analysis_type", "party_role", "dialog_type", "date", "hour", "day_of_week"];
  };
  filters?: {
    type: "object";
    description: "Filters to apply before aggregation";
  };
  metrics?: {
    type: "array";
    items: { type: "string"; enum: ["count", "avg_duration", "party_count", "dialog_count"] };
    default: ["count"];
  };
}
```

**Features:**

* Group by various dimensions
* Multiple aggregation metrics
* Pre-aggregation filtering

***

## 4. Tag Management System

Tags in vCon are **key-value pairs stored as a special attachment** with `type: "tag"`. They provide simple, flexible metadata for categorization, filtering, and organization. The Python vCon library uses `vcon.add_tag()` which creates these special attachments behind the scenes.

### 4.1 Core Tag Operations

#### `add_tag` Tool

Add or update a tag on a vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  key: {
    type: "string";
    required: true;
    description: "Tag key/name";
  };
  value: {
    type: ["string", "number", "boolean"];
    required: true;
    description: "Tag value";
  };
  overwrite?: {
    type: "boolean";
    default: true;
    description: "Overwrite if tag already exists";
  };
}
```

**Features:**

* String, number, or boolean values
* Automatic type handling
* Overwrite protection option
* Creates tag attachment if none exists

**Examples:**

```typescript
// Customer identification
add_tag(uuid, "customer_id", "CUST-12345")

// Interaction tracking
add_tag(uuid, "interaction_id", "INT-2024-001")

// Business metadata
add_tag(uuid, "department", "sales")
add_tag(uuid, "priority", "high")
add_tag(uuid, "resolved", true)

// Campaign tracking
add_tag(uuid, "campaign", "spring_2024")
add_tag(uuid, "source", "web_chat")

// Quality scores
add_tag(uuid, "quality_score", 8.5)
add_tag(uuid, "csat", 4)
```

#### `get_tag` Tool

Retrieve a specific tag value.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  key: {
    type: "string";
    required: true;
    description: "Tag key to retrieve";
  };
  default_value?: {
    type: ["string", "number", "boolean", "null"];
    description: "Value to return if tag doesn't exist";
  };
}
```

**Response:**

```typescript
{
  key: string;
  value: string | number | boolean | null;
  exists: boolean;
}
```

#### `get_all_tags` Tool

Get all tags for a vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  filter_prefix?: {
    type: "string";
    description: "Only return tags starting with this prefix (e.g., 'customer_')";
  };
}
```

**Response:**

```typescript
{
  tags: Record<string, string | number | boolean>;
  count: number;
}
```

**Example Response:**

```json
{
  "tags": {
    "customer_id": "CUST-12345",
    "interaction_id": "INT-2024-001",
    "department": "sales",
    "priority": "high",
    "resolved": true,
    "quality_score": 8.5
  },
  "count": 6
}
```

#### `remove_tag` Tool

Remove a tag from a vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  key: {
    type: "string";
    required: true;
    description: "Tag key to remove";
  };
}
```

#### `update_tags` Tool

Update multiple tags at once.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  tags: {
    type: "object";
    required: true;
    description: "Key-value pairs to add/update";
  };
  merge?: {
    type: "boolean";
    default: true;
    description: "Merge with existing tags vs replace all";
  };
}
```

**Example:**

```typescript
update_tags(uuid, {
  "status": "closed",
  "resolution": "resolved",
  "resolution_time": 1842,  // seconds
  "follow_up_required": false
}, merge: true)
```

### 4.2 Bulk Tag Operations

#### `bulk_add_tags` Tool

Add same tag(s) to multiple vCons.

**Input Schema:**

```typescript
{
  vcon_uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
    required: true;
  };
  tags: {
    type: "object";
    required: true;
    description: "Tags to add to all vCons";
  };
  overwrite?: {
    type: "boolean";
    default: true;
  };
}
```

**Example Use Cases:**

```typescript
// Tag all conversations from a campaign
bulk_add_tags(campaign_vcon_uuids, {
  "campaign": "summer_promo_2024",
  "tagged_date": "2024-06-15"
})

// Mark conversations for review
bulk_add_tags(flagged_uuids, {
  "needs_review": true,
  "flagged_by": "quality_system"
})

// Update department after reorganization
bulk_add_tags(sales_team_uuids, {
  "department": "revenue_operations"
})
```

#### `bulk_remove_tags` Tool

Remove tag(s) from multiple vCons.

**Input Schema:**

```typescript
{
  vcon_uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
    required: true;
  };
  tag_keys: {
    type: "array";
    items: { type: "string" };
    required: true;
    description: "Tag keys to remove";
  };
}
```

#### `bulk_tag_by_search` Tool

Tag all vCons matching search criteria.

**Input Schema:**

```typescript
{
  search_criteria: {
    type: "object";
    required: true;
    description: "Search criteria to find vCons to tag";
  };
  tags: {
    type: "object";
    required: true;
    description: "Tags to apply";
  };
  preview?: {
    type: "boolean";
    default: false;
    description: "Preview how many vCons would be tagged";
  };
  max_count?: {
    type: "integer";
    description: "Maximum number of vCons to tag";
  };
}
```

**Example:**

```typescript
// Tag all unresolved high-priority conversations
bulk_tag_by_search({
  tags: { priority: "high", resolved: false },
  date_range: { start: "2024-01-01", end: "2024-06-30" }
}, {
  "needs_escalation": true,
  "escalation_date": "2024-07-01"
})
```

### 4.3 Tag-Based Search & Filtering

#### `search_by_tags` Tool

Find vCons by tag criteria.

**Input Schema:**

```typescript
{
  tags: {
    type: "object";
    required: true;
    description: "Tag criteria (all must match)";
  };
  match_mode?: {
    type: "string";
    enum: ["all", "any", "exact"];
    default: "all";
    description: "How to match multiple tags";
  };
  include_components?: {
    type: "array";
    items: { type: "string"; enum: ["parties", "dialog", "attachments", "analysis", "metadata"] };
    default: ["metadata"];
  };
  limit?: {
    type: "integer";
    default: 100;
  };
  offset?: {
    type: "integer";
    default: 0;
  };
}
```

**Match Modes:**

* **all**: vCon must have ALL specified tags with matching values (AND)
* **any**: vCon must have ANY of the specified tags (OR)
* **exact**: vCon must have EXACTLY these tags, no more, no less

**Examples:**

```typescript
// Find all high-priority sales conversations
search_by_tags({
  department: "sales",
  priority: "high"
}, match_mode: "all")

// Find conversations needing review OR escalation
search_by_tags({
  needs_review: true,
  needs_escalation: true
}, match_mode: "any")

// Find conversations with specific campaign tag
search_by_tags({
  campaign: "spring_2024"
})
```

#### `search_by_tag_prefix` Tool

Find vCons with tags matching a prefix.

**Input Schema:**

```typescript
{
  prefix: {
    type: "string";
    required: true;
    description: "Tag key prefix to match";
  };
  value_filter?: {
    type: "string";
    description: "Optional value filter";
  };
  limit?: { type: "integer"; default: 100 };
}
```

**Example:**

```typescript
// Find all vCons with any customer-related tags
search_by_tag_prefix("customer_")

// Returns vCons with tags like:
// customer_id, customer_name, customer_tier, etc.
```

#### `search_by_tag_pattern` Tool

Advanced tag search with wildcards.

**Input Schema:**

```typescript
{
  pattern: {
    type: "object";
    required: true;
    description: "Tag patterns with wildcards";
  };
  limit?: { type: "integer"; default: 100 };
}
```

**Example:**

```typescript
// Find conversations tagged with any Q1 campaign
search_by_tag_pattern({
  campaign: "q1_*"
})

// Find conversations with numeric quality scores above threshold
search_by_tag_pattern({
  quality_score: ">8.0"
})
```

### 4.4 Tag Analytics & Reporting

#### `get_tag_statistics` Tool

Get statistics about tag usage.

**Input Schema:**

```typescript
{
  tag_key?: {
    type: "string";
    description: "Specific tag key to analyze, or all if omitted";
  };
  date_range?: {
    type: "object";
    properties: {
      start: { type: "string"; format: "date-time" };
      end: { type: "string"; format: "date-time" };
    };
  };
}
```

**Response:**

```typescript
{
  tag_key: string;
  total_occurrences: number;
  unique_values: number;
  value_distribution: Record<string, number>;
  most_common_values: Array<{ value: string | number | boolean; count: number }>;
  data_types: Array<"string" | "number" | "boolean">;
}
```

**Example Response:**

```json
{
  "tag_key": "department",
  "total_occurrences": 15420,
  "unique_values": 8,
  "value_distribution": {
    "sales": 6200,
    "support": 5100,
    "billing": 2800,
    "technical": 1320
  },
  "most_common_values": [
    { "value": "sales", "count": 6200 },
    { "value": "support", "count": 5100 },
    { "value": "billing", "count": 2800 }
  ],
  "data_types": ["string"]
}
```

#### `get_all_tag_keys` Tool

List all unique tag keys in the database.

**Input Schema:**

```typescript
{
  sort_by?: {
    type: "string";
    enum: ["alphabetical", "frequency", "recent"];
    default: "alphabetical";
  };
  limit?: {
    type: "integer";
    default: 100;
  };
}
```

**Response:**

```typescript
{
  tag_keys: Array<{
    key: string;
    count: number;
    data_types: string[];
    first_seen: string; // ISO timestamp
    last_seen: string; // ISO timestamp
  }>;
  total_unique_keys: number;
}
```

#### `suggest_tags` Tool

Get tag suggestions based on vCon content.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  suggestion_sources?: {
    type: "array";
    items: { type: "string"; enum: ["subject", "parties", "dialog_content", "analysis", "similar_vcons"] };
    default: ["subject", "parties", "similar_vcons"];
  };
  max_suggestions?: {
    type: "integer";
    default: 10;
  };
}
```

**Response:**

```typescript
{
  suggested_tags: Array<{
    key: string;
    value: string | number | boolean;
    confidence: number; // 0-1
    source: string;
    reason: string;
  }>;
}
```

**Example Response:**

```json
{
  "suggested_tags": [
    {
      "key": "department",
      "value": "sales",
      "confidence": 0.92,
      "source": "dialog_content",
      "reason": "Multiple mentions of 'sales quota', 'sales team'"
    },
    {
      "key": "priority",
      "value": "high",
      "confidence": 0.78,
      "source": "similar_vcons",
      "reason": "Similar conversations are tagged high priority"
    },
    {
      "key": "product",
      "value": "enterprise_suite",
      "confidence": 0.85,
      "source": "subject",
      "reason": "Subject contains 'Enterprise Suite Demo'"
    }
  ]
}
```

### 4.5 Tag Templates & Presets

#### `create_tag_template` Tool

Create reusable tag templates.

**Input Schema:**

```typescript
{
  template_name: {
    type: "string";
    required: true;
  };
  tags: {
    type: "object";
    required: true;
    description: "Default tag key-value pairs";
  };
  variables?: {
    type: "array";
    items: { type: "string" };
    description: "Tag keys that should be filled in per-use";
  };
  description?: {
    type: "string";
  };
}
```

**Example:**

```typescript
// Create a customer support template
create_tag_template(
  "customer_support_call",
  {
    department: "support",
    type: "phone_call",
    recorded: true,
    // Variables to be filled in:
    // agent_id, customer_id, ticket_id, resolution
  },
  variables: ["agent_id", "customer_id", "ticket_id", "resolution"]
)
```

#### `apply_tag_template` Tool

Apply a template to a vCon.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  template_name: {
    type: "string";
    required: true;
  };
  variable_values?: {
    type: "object";
    description: "Values for template variables";
  };
}
```

**Example:**

```typescript
apply_tag_template(uuid, "customer_support_call", {
  agent_id: "AGENT-123",
  customer_id: "CUST-456",
  ticket_id: "TICKET-789",
  resolution: "resolved"
})
```

#### `list_tag_templates` Tool

List available tag templates.

**Response:**

```typescript
{
  templates: Array<{
    name: string;
    description: string;
    tags: object;
    variables: string[];
    usage_count: number;
  }>;
}
```

### 4.6 Tag Validation & Cleanup

#### `validate_tags` Tool

Validate tags across vCons.

**Input Schema:**

```typescript
{
  vcon_uuid?: {
    type: "string";
    format: "uuid";
    description: "Validate specific vCon, or all if omitted";
  };
  rules?: {
    type: "array";
    items: {
      type: "object";
      properties: {
        key: { type: "string" };
        required?: { type: "boolean" };
        data_type?: { type: "string"; enum: ["string", "number", "boolean"] };
        allowed_values?: { type: "array" };
        pattern?: { type: "string"; description: "Regex pattern" };
      };
    };
  };
}
```

**Example:**

```typescript
validate_tags(uuid, rules: [
  {
    key: "department",
    required: true,
    allowed_values: ["sales", "support", "billing", "technical"]
  },
  {
    key: "customer_id",
    required: true,
    pattern: "^CUST-\\d{4,}$"
  },
  {
    key: "priority",
    allowed_values: ["low", "medium", "high", "urgent"]
  }
])
```

#### `cleanup_tags` Tool

Clean up malformed or deprecated tags.

**Input Schema:**

```typescript
{
  operations: {
    type: "array";
    items: {
      type: "string";
      enum: [
        "remove_empty_values",
        "normalize_case",
        "trim_whitespace",
        "remove_deprecated_keys",
        "standardize_types",
        "remove_duplicates"
      ];
    };
    required: true;
  };
  deprecated_keys?: {
    type: "array";
    items: { type: "string" };
    description: "Tag keys to remove";
  };
  dry_run?: {
    type: "boolean";
    default: true;
  };
}
```

### 4.7 Tag Resources (MCP URI Access)

```typescript
"vcon://v1/vcons/{uuid}/tags": {
  description: "Get all tags for a vCon";
  mimeType: "application/json";
}

"vcon://v1/vcons/{uuid}/tags/{key}": {
  description: "Get specific tag value";
  mimeType: "application/json";
}

"vcon://v1/tags/search": {
  description: "Search vCons by tags";
  mimeType: "application/json";
  parameters: {
    tags: object;
    match_mode?: "all" | "any" | "exact";
  };
}

"vcon://v1/tags/keys": {
  description: "List all unique tag keys";
  mimeType: "application/json";
}

"vcon://v1/tags/stats": {
  description: "Tag usage statistics";
  mimeType: "application/json";
  parameters: {
    tag_key?: string;
  };
}

"vcon://v1/tags/templates": {
  description: "List tag templates";
  mimeType: "application/json";
}
```

### 4.8 Common Tag Patterns

#### Standard Business Tags

```typescript
// Customer relationship
{
  "customer_id": "CUST-12345",
  "customer_name": "Acme Corp",
  "customer_tier": "enterprise",
  "customer_segment": "b2b"
}

// Interaction tracking
{
  "interaction_id": "INT-2024-001",
  "interaction_type": "support_call",
  "channel": "phone",
  "interaction_date": "2024-01-15"
}

// Agent/employee tracking
{
  "agent_id": "AGENT-789",
  "agent_name": "Sarah Johnson",
  "team": "support_tier_2",
  "supervisor": "MGR-045"
}

// Categorization
{
  "department": "sales",
  "product": "enterprise_suite",
  "region": "north_america",
  "language": "en-US"
}

// Status tracking
{
  "status": "closed",
  "resolution": "resolved",
  "escalated": false,
  "follow_up_required": true,
  "follow_up_date": "2024-01-20"
}

// Quality & metrics
{
  "quality_score": 8.5,
  "csat": 4,
  "nps": 9,
  "handled_by_bot": false,
  "first_contact_resolution": true
}

// Compliance & legal
{
  "recorded": true,
  "recording_consent": true,
  "retention_period_days": 2555,
  "data_classification": "confidential"
}
```

***

## 5. Batch & Bulk Operations

### 5.1 Batch Import

#### `import_vcons_batch` Tool

Import multiple vCons from array.

**Input Schema:**

```typescript
{
  vcons: {
    type: "array";
    items: { type: "object" };
    description: "Array of vCon objects";
    required: true;
  };
  validate_all?: {
    type: "boolean";
    default: true;
    description: "Validate all vCons before inserting any";
  };
  continue_on_error?: {
    type: "boolean";
    default: false;
    description: "Continue importing valid vCons if some fail";
  };
  return_results?: {
    type: "boolean";
    default: true;
    description: "Return detailed import results";
  };
}
```

**Response:**

```typescript
{
  total: number;
  successful: number;
  failed: number;
  errors: Array<{ index: number; error: string; vcon_uuid?: string }>;
  imported_uuids: string[];
}
```

#### `import_vcons_from_file` Tool

Import vCons from file.

**Input Schema:**

```typescript
{
  file_path: {
    type: "string";
    description: "Path to JSON file or JSONL file";
    required: true;
  };
  format: {
    type: "string";
    enum: ["json_array", "jsonl", "auto_detect"];
    default: "auto_detect";
  };
  batch_size?: {
    type: "integer";
    default: 100;
    description: "Number of vCons to process per batch";
  };
  validate_all?: { type: "boolean"; default: true };
  continue_on_error?: { type: "boolean"; default: false };
}
```

**Features:**

* JSON array format support
* JSONL (newline-delimited JSON) support
* Batched processing for large files
* Error handling options

#### `import_vcons_from_url` Tool

Import vCons from remote URL.

**Input Schema:**

```typescript
{
  url: {
    type: "string";
    format: "uri";
    required: true;
  };
  format: {
    type: "string";
    enum: ["json_array", "jsonl", "auto_detect"];
    default: "auto_detect";
  };
  headers?: {
    type: "object";
    description: "HTTP headers for request";
  };
  auth?: {
    type: "object";
    properties: {
      type: { type: "string"; enum: ["basic", "bearer", "api_key"] };
      credentials: { type: "object" };
    };
  };
}
```

### 4.2 Batch Export

#### `export_vcons_batch` Tool

Export multiple vCons.

**Input Schema:**

```typescript
{
  uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
    description: "UUIDs to export";
  };
  search_criteria?: {
    type: "object";
    description: "Alternative to UUIDs - export by search";
  };
  format: {
    type: "string";
    enum: ["json_array", "jsonl", "individual_files"];
    default: "json_array";
  };
  output_path?: {
    type: "string";
    description: "File path or directory for export";
  };
  include_components?: {
    type: "array";
    items: { type: "string"; enum: ["parties", "dialog", "attachments", "analysis", "all"] };
    default: ["all"];
  };
  compression?: {
    type: "string";
    enum: ["none", "gzip", "zip"];
    default: "none";
  };
}
```

**Features:**

* Multiple export formats
* Selective component export
* Compression options
* File or in-memory export

#### `export_to_url` Tool

POST vCons to external URL.

**Input Schema:**

```typescript
{
  uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
  };
  destination_url: {
    type: "string";
    format: "uri";
    required: true;
  };
  batch_size?: {
    type: "integer";
    default: 10;
    description: "Number of vCons per HTTP request";
  };
  headers?: {
    type: "object";
  };
  auth?: {
    type: "object";
  };
  retry_on_failure?: {
    type: "boolean";
    default: true;
  };
  max_retries?: {
    type: "integer";
    default: 3;
  };
}
```

### 4.3 Batch Updates

#### `bulk_update_vcons` Tool

Update multiple vCons at once.

**Input Schema:**

```typescript
{
  uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
  };
  updates: {
    type: "object";
    description: "Updates to apply to all vCons";
    required: true;
  };
  merge_strategy?: {
    type: "string";
    enum: ["replace", "merge", "append"];
    default: "merge";
  };
}
```

#### `bulk_tag_vcons` Tool

Add/remove tags from multiple vCons.

**Input Schema:**

```typescript
{
  uuids: {
    type: "array";
    items: { type: "string"; format: "uuid" };
  };
  tags_to_add?: {
    type: "object";
    description: "Tags to add (key-value pairs)";
  };
  tags_to_remove?: {
    type: "array";
    items: { type: "string" };
    description: "Tag keys to remove";
  };
}
```

***

## 5. Validation & Quality Operations

### 5.1 Validation

#### `validate_vcon` Tool

Validate vCon against IETF specification.

**Input Schema:**

```typescript
{
  vcon_uuid?: {
    type: "string";
    format: "uuid";
    description: "Validate stored vCon";
  };
  vcon_data?: {
    type: "object";
    description: "Validate provided vCon object";
  };
  strict_mode?: {
    type: "boolean";
    default: false;
    description: "Enforce strict compliance vs lenient";
  };
  check_references?: {
    type: "boolean";
    default: true;
    description: "Validate party/dialog index references";
  };
}
```

**Response:**

```typescript
{
  valid: boolean;
  errors: Array<{
    field: string;
    message: string;
    severity: "error" | "warning";
  }>;
  warnings: string[];
  compliance_level: "full" | "partial" | "non_compliant";
}
```

#### `validate_vcons_batch` Tool

Batch validation.

**Input Schema:**

```typescript
{
  uuids?: {
    type: "array";
    items: { type: "string"; format: "uuid" };
  };
  search_criteria?: {
    type: "object";
    description: "Validate all matching vCons";
  };
  parallel_processing?: {
    type: "boolean";
    default: true;
  };
}
```

**Response:**

```typescript
{
  total: number;
  valid: number;
  invalid: number;
  results: Array<{
    uuid: string;
    valid: boolean;
    errors: string[];
  }>;
}
```

### 5.2 Data Quality

#### `check_data_quality` Tool

Run data quality checks.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  checks: {
    type: "array";
    items: {
      type: "string";
      enum: [
        "missing_parties",
        "empty_dialogs",
        "orphaned_references",
        "invalid_timestamps",
        "missing_required_fields",
        "duplicate_parties",
        "invalid_urls",
        "encoding_issues"
      ];
    };
    default: ["all"];
  };
}
```

**Response:**

```typescript
{
  quality_score: number; // 0-100
  issues: Array<{
    check: string;
    severity: "critical" | "warning" | "info";
    message: string;
    suggested_fix?: string;
  }>;
  passed_checks: string[];
  failed_checks: string[];
}
```

#### `repair_vcon` Tool

Attempt automatic repair of vCon issues.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  repair_actions: {
    type: "array";
    items: {
      type: "string";
      enum: [
        "fix_timestamps",
        "remove_orphaned_references",
        "add_missing_uuids",
        "normalize_encodings",
        "deduplicate_parties"
      ];
    };
  };
  dry_run?: {
    type: "boolean";
    default: true;
    description: "Preview changes without applying";
  };
}
```

***

## 6. Analysis & Insight Operations (Non-Compliance)

### 6.1 Content Analysis

#### `analyze_conversation` Prompt

Generic analysis workflow.

**Arguments:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
    required: true;
  };
  analysis_type: {
    type: "string";
    enum: ["sentiment", "summary", "topics", "entities", "keywords", "language_detection", "custom"];
    required: true;
  };
  parameters?: {
    type: "object";
    description: "Analysis-specific parameters";
  };
  save_to_vcon?: {
    type: "boolean";
    default: true;
    description: "Save results as analysis entry";
  };
}
```

**Features:**

* Sentiment analysis
* Conversation summarization
* Topic extraction
* Named entity recognition
* Keyword extraction
* Language detection
* Custom analysis pipelines

#### `extract_insights` Prompt

Extract specific insights.

**Arguments:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  insight_types: {
    type: "array";
    items: {
      type: "string";
      enum: [
        "key_topics",
        "action_items",
        "decisions_made",
        "questions_asked",
        "participant_sentiment",
        "conversation_flow",
        "important_quotes"
      ];
    };
    required: true;
  };
  format?: {
    type: "string";
    enum: ["json", "markdown", "text"];
    default: "json";
  };
}
```

### 6.2 Transcription (Integration Ready)

#### `transcribe_dialog` Tool

Transcribe audio/video dialog.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  dialog_index: {
    type: "integer";
    minimum: 0;
  };
  service: {
    type: "string";
    enum: ["deepgram", "whisper", "google_speech", "aws_transcribe", "custom"];
    description: "Transcription service to use";
  };
  options?: {
    type: "object";
    properties: {
      language?: { type: "string" };
      model?: { type: "string" };
      punctuation?: { type: "boolean" };
      diarization?: { type: "boolean" };
      timestamps?: { type: "boolean" };
    };
  };
  save_as_analysis?: {
    type: "boolean";
    default: true;
  };
}
```

**Features:**

* Multiple transcription service support
* Speaker diarization
* Timestamp generation
* Language detection
* Automatic save to analysis

***

## 7. MCP Resources (URI-based Access)

### 7.1 Direct vCon Access

```typescript
"vcon://uuid/{uuid}": {
  description: "Get complete vCon by UUID";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/parties": {
  description: "Get parties array";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/dialog": {
  description: "Get dialog array";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/dialog/{index}": {
  description: "Get specific dialog by index";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/attachments": {
  description: "Get attachments array";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/attachments/{index}": {
  description: "Get specific attachment by index";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/analysis": {
  description: "Get all analysis results";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/analysis/{type}": {
  description: "Get analysis by type";
  mimeType: "application/json";
}

"vcon://uuid/{uuid}/metadata": {
  description: "Get vCon metadata only (no content)";
  mimeType: "application/json";
}
```

### 7.2 Search Resources

```typescript
"vcon://search": {
  description: "Search vCons with query parameters";
  mimeType: "application/json";
  parameters: {
    q?: string; // query
    subject?: string;
    party?: string;
    type?: string;
    limit?: number;
    offset?: number;
  };
}

"vcon://recent": {
  description: "Get most recent vCons";
  mimeType: "application/json";
  parameters: {
    limit?: number;
    hours?: number;
  };
}
```

### 7.3 Aggregate Resources

```typescript
"vcon://stats/summary": {
  description: "Database summary statistics";
  mimeType: "application/json";
  content: {
    total_vcons: number;
    total_parties: number;
    total_dialogs: number;
    total_analysis: number;
    by_type: Record<string, number>;
    by_status: Record<string, number>;
  };
}

"vcon://stats/analysis_types": {
  description: "Analysis types with counts";
  mimeType: "application/json";
}

"vcon://stats/party_roles": {
  description: "Party roles distribution";
  mimeType: "application/json";
}

"vcon://stats/dialog_types": {
  description: "Dialog types distribution";
  mimeType: "application/json";
}
```

***

## 8. Format Conversion & Export

### 8.1 Format Conversion

#### `export_vcon` Prompt

Export in various formats.

**Arguments:**

```typescript
{
  uuid: {
    type: "string";
    format: "uuid";
  };
  format: {
    type: "string";
    enum: ["standard", "minimal", "readable", "csv", "html"];
    default: "standard";
  };
  include_binary?: {
    type: "boolean";
    default: false;
    description: "Include base64 binary data";
  };
  compression?: {
    type: "string";
    enum: ["none", "gzip", "zip"];
    default: "none";
  };
}
```

**Formats:**

* **standard**: Full IETF vCon JSON
* **minimal**: Metadata + references only
* **readable**: Human-readable HTML or Markdown
* **csv**: Flattened CSV export (for dialogs/parties)
* **html**: Formatted HTML view

#### `convert_format` Tool

Convert between vCon versions.

**Input Schema:**

```typescript
{
  vcon_uuid: {
    type: "string";
    format: "uuid";
  };
  target_version: {
    type: "string";
    enum: ["0.0.1", "0.0.2", "latest"];
    default: "latest";
  };
  preserve_extensions?: {
    type: "boolean";
    default: true;
  };
}
```

***

## 9. Database & System Operations

### 9.1 Database Management

#### `database_stats` Tool

Get database statistics.

**Response:**

```typescript
{
  total_vcons: number;
  total_parties: number;
  total_dialogs: number;
  total_attachments: number;
  total_analysis: number;
  database_size_mb: number;
  oldest_vcon: string; // ISO timestamp
  newest_vcon: string; // ISO timestamp
  by_analysis_type: Record<string, number>;
  by_dialog_type: Record<string, number>;
}
```

#### `vacuum_database` Tool

Clean up and optimize database.

**Input Schema:**

```typescript
{
  remove_orphaned_records?: {
    type: "boolean";
    default: true;
  };
  analyze_tables?: {
    type: "boolean";
    default: true;
  };
  rebuild_indexes?: {
    type: "boolean";
    default: false;
  };
}
```

### 9.2 Health Checks

#### `health_check` Tool

Server health status.

**Response:**

```typescript
{
  status: "healthy" | "degraded" | "unhealthy";
  database_connection: boolean;
  response_time_ms: number;
  version: string;
  uptime_seconds: number;
  last_error?: string;
}
```

***

## 10. Webhook & Event System (Open Source)

### 10.1 Webhook Configuration

#### `configure_webhook` Tool

Set up webhooks for events.

**Input Schema:**

```typescript
{
  webhook_url: {
    type: "string";
    format: "uri";
    required: true;
  };
  events: {
    type: "array";
    items: {
      type: "string";
      enum: [
        "vcon.created",
        "vcon.updated",
        "vcon.deleted",
        "dialog.added",
        "analysis.added",
        "validation.failed"
      ];
    };
    required: true;
  };
  auth?: {
    type: "object";
    properties: {
      type: { type: "string"; enum: ["basic", "bearer", "api_key"] };
      credentials: { type: "object" };
    };
  };
  retry_policy?: {
    type: "object";
    properties: {
      max_retries: { type: "integer"; default: 3 };
      retry_delay_ms: { type: "integer"; default: 1000 };
    };
  };
}
```

***

## 11. Developer Features

### 11.1 Schema & Documentation

#### `get_schema` Tool

Get vCon schema definition.

**Input Schema:**

```typescript
{
  version?: {
    type: "string";
    default: "latest";
  };
  format?: {
    type: "string";
    enum: ["json_schema", "typescript", "openapi"];
    default: "json_schema";
  };
}
```

#### `get_examples` Tool

Get example vCons.

**Input Schema:**

```typescript
{
  example_type: {
    type: "string";
    enum: ["minimal", "phone_call", "chat", "email", "video", "full_featured"];
  };
  format?: {
    type: "string";
    enum: ["json", "yaml"];
    default: "json";
  };
}
```

***

## Summary of Open Source Features

### Core Capabilities

✅ Full CRUD operations for vCons ✅ Component management (parties, dialog, attachments, analysis) ✅ Advanced search and filtering ✅ Batch import/export ✅ Validation and data quality checks ✅ Basic analysis (sentiment, topics, summaries) ✅ Format conversion ✅ Webhook system ✅ Full-text search ✅ Aggregation and statistics ✅ MCP Resources (URI-based access)

### What's NOT Included (Proprietary)

❌ Consent management ❌ Privacy request handling (GDPR/CCPA) ❌ Compliance checking ❌ Access logging with audit trails ❌ Privacy-level data filtering ❌ PII detection and masking (beyond basic) ❌ Data retention enforcement ❌ Transparency service integration ❌ Regulatory compliance workflows

This makes the open source version extremely valuable for:

* Development and testing
* Non-regulated use cases
* Custom implementations
* Academic research
* Community building

While the proprietary version is essential for:

* Healthcare (HIPAA)
* Finance (PCI)
* EU operations (GDPR)
* California operations (CCPA)
* Enterprise compliance needs


# Glossary

Terms and definitions for the vCon MCP Server.

***

## A

### Analysis

A component of a vCon containing results from AI/ML processing such as transcription, sentiment analysis, or summarization. Stored in the `analysis` array. See [Section 4.5](/reference/vcon-spec#analysis-object) of the vCon spec.

### Attachment

A component of a vCon for supporting files, notes, or metadata. Used for tags, documents, and custom data. Stored in the `attachments` array. See [Section 4.4](/reference/vcon-spec#attachment-object).

### Async/Await

JavaScript/TypeScript pattern for handling asynchronous operations. Used throughout the server for database queries and API calls.

***

## B

### Base64url

URL-safe base64 encoding scheme defined in RFC 4648. One of three valid `encoding` values in vCon. See [Encoding Options](/reference/vcon-spec#encoding-options).

***

## C

### CCPA

California Consumer Privacy Act. US state law regulating data privacy for California residents. Supported by the Privacy Suite plugin.

### Consent

Permission from a data subject for processing their personal data. In vCon, stored as special attachments. See [Enterprise Features](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/enterprise-features.md#consent-management).

### CRUD

Create, Read, Update, Delete. Basic database operations implemented as MCP tools.

***

## D

### Database Inspector

Tool for examining vCon database structure and contents. Part of the development toolset.

### Dialog

A component of a vCon representing conversation content (recordings, text, transfers). Stored in the `dialog` array. See [Section 4.3](/reference/vcon-spec#dialog-object).

### Dialog Type

One of four valid values for `dialog.type`: `recording`, `text`, `transfer`, `incomplete`. See [Dialog Types](/reference/vcon-spec#dialog-types).

***

## E

### Embedding

Vector representation of text used for semantic search. Generated by AI models like OpenAI's text-embedding-ada-002. See [Embeddings Guide](/development/embeddings).

### Encoding

Format of content in `body` fields. Valid values: `none`, `base64url`, `json`. Must be explicitly set, no defaults. See [Encoding Options](/reference/vcon-spec#encoding-options).

### Extension

Custom functionality added to vCon spec. Declared in `extensions` array, required ones in `must_support` array. See [Extensions](/reference/vcon-spec#extensions).

***

## F

### Full-Text Search

Search using PostgreSQL's text search capabilities with trigram matching. Implemented in `search_vcons_keyword` RPC function.

***

## G

### GDPR

General Data Protection Regulation. EU law regulating data privacy and protection. Supported by the Privacy Suite plugin.

### Group

Optional vCon component for linking related conversations. Stored in `group` array. See [vCon spec Section 4.6](/reference/vcon-spec).

***

## H

### HIPAA

Health Insurance Portability and Accountability Act. US law regulating healthcare data. Supported by the Privacy Suite plugin with PHI detection.

### Hook

Extension point in the plugin system. Examples: `beforeCreate`, `afterRead`. See [Plugin Development](/development/plugins).

### HNSW

Hierarchical Navigable Small World. Algorithm for approximate nearest neighbor search used by pgvector for vector similarity. See [Vector Search](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/vector-search.md).

### Hybrid Search

Search combining keyword matching and semantic similarity. Implemented in `search_vcons_hybrid` RPC function. See [Search Guide](/guide/search).

***

## I

### IETF

Internet Engineering Task Force. Standards organization that publishes the vCon specification.

***

## J

### JSON

JavaScript Object Notation. Data format used for vCon objects. Also a valid `encoding` value.

### JSON Schema

Format for validating JSON structure. Used in MCP tool definitions.

### JWE

JSON Web Encryption. Standard for encrypting vCon objects. See [Security](/reference/vcon-spec#security).

### JWS

JSON Web Signature. Standard for signing vCon objects. See [Security](/reference/vcon-spec#security).

***

## L

### Lifecycle Hook

Plugin callback executed at specific points in vCon operations. Examples: initialization, creation, deletion. See [Plugin Interface](/development/plugins#plugin-interface).

***

## M

### Materialized View

Precomputed database query result stored as a table. Used for fast tag lookups (`vcon_tags_mv`). See [Tag System](/guide/tags).

### MCP

Model Context Protocol. Standard protocol for connecting AI assistants to data sources and tools. See [MCP Protocol](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-protocol.md).

### Migration

Process of updating database schema or code from one version to another. See [Migration Guide](/reference/migration_guide).

***

## N

### Normalization

Database design technique of organizing data to reduce redundancy. vCon data is stored in normalized form (separate tables for parties, dialog, etc.). See [Database Schema](/reference/corrected_schema).

***

## O

### OpenAI

AI company providing models for embeddings, transcription, and analysis. Used for semantic search and content analysis.

***

## P

### Party

A participant in a vCon conversation. Stored in the `parties` array. See [Section 4.2](/reference/vcon-spec#party-object).

### pgvector

PostgreSQL extension for storing and querying vector embeddings. Enables semantic search. See [Vector Search](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/vector-search.md).

### PII

Personally Identifiable Information. Data that can identify individuals. Detected and protected by Privacy Suite plugin.

### Plugin

Extension module that adds functionality to the vCon MCP Server. See [Plugin Development](/development/plugins).

### Prompt

Named template for common queries in MCP. Provides guidance to AI assistants. See [Prompts](/api-reference/prompts).

***

## Q

### Query

Database request for data. Implemented in `src/db/queries.ts`. Also refers to search terms.

***

## R

### Redaction

Process of hiding or removing sensitive information. Supported via privacy levels. See [Privacy Features](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/enterprise-features.md#privacy-levels).

### Resource

URI-based data access in MCP. Examples: `vcon://v1/vcons/{uuid}`, `vcon://v1/vcons/recent`. See [Resources](/api-reference/resources).

### RLS

Row Level Security. PostgreSQL feature for access control at the row level. Can be enabled for multi-tenant deployments.

### RPC

Remote Procedure Call. Database functions callable via Supabase. Examples: `search_vcons_keyword`, `search_vcons_semantic`.

***

## S

### Schema (Analysis)

Field in Analysis object identifying result structure. **Not** `schema_version`. See [Analysis Object](/reference/vcon-spec#analysis-object).

### Schema (Database)

Structure of database tables, columns, and relationships. See [Database Schema](/reference/corrected_schema).

### SCITT

Supply Chain Integrity, Transparency, and Trust. Standard for transparency services. Used by Privacy Suite for consent receipts.

### Semantic Search

AI-powered search using meaning rather than keywords. Uses vector embeddings and cosine similarity. Implemented in `search_vcons_semantic`. See [Search Guide](/guide/search).

### Stdio

Standard Input/Output. Transport used by MCP for communication between server and client.

### Supabase

PostgreSQL database platform with REST API, authentication, and real-time features. Backend for vCon MCP Server.

***

## T

### Tag

Key-value pair for metadata. Stored as special attachments with `type: "tags"`. See [Tag Guide](/guide/tags).

### Tool

MCP operation that can be invoked by AI assistants. Examples: `create_vcon`, `search_vcons`. See [Tools](/api-reference/tools).

### Transcript

Text version of audio/video conversation. Created by analysis tools like Deepgram or Whisper. Stored as Analysis object.

### Type Safety

Programming language feature ensuring values match expected types. Enforced by TypeScript compiler.

### TypeScript

Programming language adding static types to JavaScript. Used throughout the server codebase.

***

## U

### URI

Uniform Resource Identifier. Used by MCP resources. Examples: `vcon://v1/vcons/{uuid}`, `vcon://v1/vcons/recent/{count}`.

### UUID

Universally Unique Identifier. RFC 4122 format. Required field in vCon main object and optional in Party object.

***

## V

### vCon

Virtual Conversation. Standard container format for conversation data. Defined by IETF spec. See [vCon Specification](/reference/vcon-spec).

### Validation

Process of checking data correctness against rules. Includes spec compliance and business rules. See [Validation Guide](/development/building#validation).

### Vector

Array of numbers representing semantic meaning of text. Used for similarity search. Typically 384 or 1536 dimensions.

### Vendor

Required field in Analysis object identifying who produced the analysis. Examples: "Deepgram", "OpenAI". See [Analysis Object](/reference/vcon-spec#analysis-object).

### Vitest

Testing framework used for unit and integration tests. See [Testing Guide](/development/testing).

### VitePress

Static site generator used for documentation. Powers the docs website.

***

## W

### Webhook

HTTP callback for event notifications. Supported for vCon lifecycle events. See [Open Source Features](/reference/features#webhook-system).

***

## Z

### Zod

TypeScript library for schema validation. Used for runtime type checking of MCP tool inputs and vCon objects.

***

## Symbols & Numbers

### 0.3.0

Current version of the vCon specification. Value for the `vcon` field. See [vCon Specification](/reference/vcon-spec).

***

## Related Documentation

* [**vCon Specification**](/reference/vcon-spec) - Complete IETF vCon reference
* [**MCP Protocol**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/reference/mcp-protocol.md) - Model Context Protocol details
* [**Quick Reference**](/reference/quick_reference) - Field corrections checklist
* [**API Reference**](https://github.com/vcon-dev/vcon-mcp/blob/main/docs/api/README.md) - Tools, resources, and prompts

***

## Acronyms Quick Reference

| Acronym | Full Name                                           | Description                        |
| ------- | --------------------------------------------------- | ---------------------------------- |
| API     | Application Programming Interface                   | Interface for software interaction |
| CCPA    | California Consumer Privacy Act                     | California privacy law             |
| CRUD    | Create, Read, Update, Delete                        | Basic data operations              |
| DID     | Decentralized Identifier                            | Distributed identity system        |
| GDPR    | General Data Protection Regulation                  | EU privacy law                     |
| HIPAA   | Health Insurance Portability and Accountability Act | US healthcare privacy law          |
| HNSW    | Hierarchical Navigable Small World                  | Vector search algorithm            |
| HTTP    | Hypertext Transfer Protocol                         | Web protocol                       |
| IETF    | Internet Engineering Task Force                     | Internet standards body            |
| JSON    | JavaScript Object Notation                          | Data format                        |
| JWE     | JSON Web Encryption                                 | Encryption standard                |
| JWS     | JSON Web Signature                                  | Signing standard                   |
| MCP     | Model Context Protocol                              | AI assistant protocol              |
| PII     | Personally Identifiable Information                 | Identifying data                   |
| REST    | Representational State Transfer                     | API architecture                   |
| RFC     | Request for Comments                                | IETF standard document             |
| RLS     | Row Level Security                                  | Database access control            |
| RPC     | Remote Procedure Call                               | Database function call             |
| SCITT   | Supply Chain Integrity, Transparency, and Trust     | Transparency standard              |
| SQL     | Structured Query Language                           | Database query language            |
| URI     | Uniform Resource Identifier                         | Resource location                  |
| URL     | Uniform Resource Locator                            | Web address                        |
| UUID    | Universally Unique Identifier                       | Unique identifier format           |
| vCon    | Virtual Conversation                                | Conversation container format      |

***

**Need to add a term?** Submit a pull request or open an issue on GitHub.

***

*Glossary maintained as part of the technical reference documentation.*


# Changelog

All notable changes to the vCon MCP Server will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## \[Unreleased]

### Fixed

* `add_analysis`/`add_dialog`/`add_attachment` (MCP tools and their REST equivalents: `POST`/`PATCH /vcons/:uuid/{analysis,dialog,attachments}`) now accept a JSON `body` (object, array, number, boolean, or null) when `encoding: "json"`, per draft-ietf-vcon-vcon-core-04 Section 2.3.2. Previously only whole-vCon creation (`create_vcon`, `POST /vcons`, `/vcons/batch`) accepted a non-string body; the per-item add/update paths rejected it with a 400/tool error. A string body is still accepted unchanged regardless of encoding. The Postgres/Supabase and MongoDB storage layers already round-tripped JSON bodies correctly (CON-1047); this closes the validation gap in front of them (CON-1113)

***

## \[1.9.2] - 2026-09-23

### Fixed

* Metadata `vcon_search` no longer fails past offset \~900. Each page used to load every vCon from row 0 up to the cursor, all at once, until the Supabase client gave out with `SEARCH_FAILED`. It now fetches one page (#93)
* Growth, size, content-volume and temporal analytics no longer multiply counts through a combined LEFT JOIN of dialog, analysis and attachments. Each child table is aggregated first, and joins target `vcons.uuid`, which the child foreign keys reference (#93)
* Attachment analytics group on `purpose`, falling back to the legacy `type`, so 0.4.0 attachments no longer report as `type: null` (#93)
* Tag analytics, `get_unique_tags` and taxonomy coverage refresh `vcon_tags_mv` when it is stale. Deployments without pg\_cron kept the view empty and reported no tags on a tagged corpus. Requires migration `20260923210000_refresh_vcon_tags_mv_if_stale.sql` (#93)
* PostgREST errors report their message instead of `[object Object]` in tool responses and batch-writer logs (#93)

***

## \[1.9.1] - 2026-09-23

### Changed

* OAuth consent page redesigned: a card with the server host, a standard Google button, and a consent step that names the signed-in account and states whether access is read-only. Buttons disable while a request is in flight. Follows the system light or dark theme and fits phone widths (#91)

### Fixed

* A request carrying a valid OAuth token no longer logs "Invalid MCP auth token attempted". The static-key check stays quiet when OAuth is enabled, and the warning is logged only when both checks reject the token (#91)

***

## \[1.9.0] - 2026-09-23

### Added

* OAuth 2.1 on the MCP HTTP endpoint so the server can be added as a custom connector in claude.ai and Claude Desktop, which only sign in with OAuth. vcon-mcp acts as the resource server: it serves protected-resource metadata (RFC 9728) at `/.well-known/oauth-protected-resource` and the resource-path variant without auth, redirects `/.well-known/oauth-authorization-server` to the issuer, answers 401 with `WWW-Authenticate: Bearer resource_metadata="..."`, and verifies JWT access tokens on every request (JWKS signature, issuer, expiry, audience equal to `OAUTH_RESOURCE`). An optional consent page at `/oauth/consent` completes the Supabase OAuth Server flow. Off unless `OAUTH_ISSUER` is set; static `API_KEYS` / `API_KEYS_READONLY` tokens are checked first and keep working. OAuth sessions are read-only unless `OAUTH_READONLY=false`. The consent page signs in by emailed code or through a Supabase external provider such as Google (`OAUTH_CONSENT_PROVIDERS`) (#89)

***

## \[1.8.0] - 2026-09-20

### Added

* `API_ANONYMOUS_READONLY=true` treats a request with no token as a read-only session: `GET`/`HEAD`/`OPTIONS` on REST, read tools over MCP. Tokens in `API_KEYS` keep full access and a wrong token is still rejected. Lets a public dataset be reached from MCP clients that cannot send a bearer header (claude.ai and ChatGPT connectors) without `API_AUTH_REQUIRED=false`, which also opens writes (#84)
* `MCP_SERVER_INSTRUCTIONS` is returned in the `instructions` field of the MCP `initialize` result, so a hosted dataset can tell a connecting agent what the corpus is, how its vCons are shaped and which tools to start with (#85)

## \[1.7.0] - 2026-09-20

### Added

* `MCP_TOOLS_PROFILE=public` for hosted, read-only datasets. A context-free agent connecting to a public corpus previously saw 28 tools on a read-only session, about half of them operator tooling (`get_database_stats`, `analyze_query`, health and growth analytics). The `public` profile keeps the read and search tools, `get_schema`, `get_examples`, and tag discovery, and hides database internals, analytics, and the two deployment-shaped tools `vcon_aggregate` and `vcon_taxonomy`. `MCP_DISABLED_TOOLS` now merges with a profile's own disabled list instead of replacing it (VCON-1716)
* Prompts carry a `category` and are filtered by the same profile and category rules as tools, in both `prompts/list` and `prompts/get`. `daily_activity_report` is `analytics`; every other prompt is `read` (VCON-1716)

### Changed

* Shared tool descriptions no longer carry one deployment's vocabulary. `vcon_aggregate`, `vcon_search`, `vcon_fetch`, and `vcon_taxonomy` describe tag filters, include groups, and the `strolid_dealer` attachment in neutral terms ("where a deployment stores one") instead of "top dealers by portal-tag rate" and `tags.portal` examples. Field names and the API contract are unchanged (VCON-1716)
* The `find_by_customer` prompt is renamed `find_by_party`, with the customer wording removed from its description and from `daily_activity_report`. Clients that request the old name get `Unknown prompt` (VCON-1716)
* `has_more` on `GET /vcons` is computed from a probe row (`limit + 1` requested, extra row withheld) instead of `vcons.length === limit`, which reported `true` on any exactly-full page and cost the client a request for an empty one. Same probe the `vcon://v1/vcons/ids` resource already used (CON-792)
* The redundant post-hoc party filter in `searchVCons` is gone; that path was already constrained by the candidate set, so it was resolving the same party lookup twice per request (CON-792)
* `vitest.config.ts` excludes `.claude/**`, so a git worktree under `.claude/worktrees` no longer doubles the local suite or drags its `tests/e2e` copies into `npm test`

### Fixed

* REST pagination honors `?offset`. `parsePagination()` parsed and validated it and the envelope reported it back, but the list handler never put it into the search filters, and neither `IVConQueries.searchVCons` nor the Supabase/Mongo implementations declared or read it — so `GET /vcons?limit=10&offset=10` returned rows 1-10 while reporting `offset: 10`. Offset now threads route -> interface -> both backends: Supabase's plain path uses `.range()`, the party-filter and tag-ordered paths slice from the offset, and Mongo uses `.skip()`. Deep paging in the tag-ordered path remains capped at `TAG_ORDERED_FETCH_CAP` (100,000 rows) (CON-790)
* Dealer-filtered metadata search returns full pages. `searchVCons` resolved `dealerMatchUuidSet()` *after* the page had been fetched and bounded, then dropped non-matching rows from it — so a dealer holding 1 in 10 of the corpus got pages of roughly one row, while `searchVConsCount` correctly reported the full total. The dealer predicate now constrains the query before the page is cut, the way the party filter already did. Reached through the `vcon_search` MCP tool (`filters.dealer_id` / `filters.dealer_name`); REST exposes no dealer parameters and was unaffected (CON-792)

***

## \[1.6.1] - 2026-08-27

### Fixed

* Declared `@opentelemetry/core`, `@opentelemetry/resources` and `@opentelemetry/sdk-metrics` as dependencies. `dist/observability/config.js` imports all three at startup, but they were never declared; they only resolved in the dev repo because npm hoisted them as transitive deps of `@opentelemetry/sdk-node`. On a clean install with a different hoisting layout the server died immediately with `ERR_MODULE_NOT_FOUND: Cannot find package '@opentelemetry/resources'`, which an MCP client surfaces only as `CONNECTION_CLOSED`. Found installing the vCon plugin, whose `.mcp.json` launches the server with `npx -y vcon-mcp` (PR #74)

***

## \[1.6.0] - 2026-08-27

### Added

* `bin` entry (`vcon-mcp` -> `dist/index.js`), so the server runs with `npx -y vcon-mcp`. `package.json` declared `main` and `exports` but no `bin`, so npm installed the package without an executable and every adopter had to clone the repo, build it, and point their MCP client at an absolute `dist/index.js` path. The entry file already carried the shebang; only the wiring was missing (PR #73)

### Changed

* README MCP client configuration examples use `npx -y vcon-mcp` instead of a hard-coded `dist/index.js` path, in both the Claude Desktop and read-only deployment samples
* `PUBLISHING_GUIDE.md` documents the tag-push release flow instead of walking a maintainer through `npm login` and `npm publish` by hand. Publishing by hand is what left v1.4.0 tagged and unpublished for three days; the guide now ends with `npm view vcon-mcp version` as the verification step, since the tag, the changelog and the registry drift apart independently

***

## \[1.5.0] - 2026-08-21

### Added

* Read-only API keys (`API_KEYS_READONLY`). `API_KEYS` was a flat list where every token granted full read, write and delete over the REST API, so there was no safe credential to hand an external consumer of a hosted dataset. Read-only tokens authenticate but are limited to `GET`/`HEAD`/`OPTIONS` on REST (403 otherwise) and to non-write MCP tools, reusing the existing `MCP_TOOLS_PROFILE` category metadata rather than a second classification. `API_KEYS` keeps full access for backward compatibility; the server warns at startup when no read-only keys are configured, a token listed in both variables is read-only (deny wins), an MCP session is pinned to the scope of the key that opened it, and plugin tools (which carry no category) are dropped from read-only sessions (PR #69)

### Fixed

* Attachment `purpose='tags'` is now treated as equivalent to `type='tags'`. vCon 0.4.0 classifies attachments with `purpose`, so tags arriving inside a spec-correct document were written with `type` NULL and were invisible to every tag read path and to `vcon_tags_mv` — silently, with no error. A `BEFORE INSERT OR UPDATE` trigger on `attachments` mirrors `tags` across both columns (with a backfill), and `vcon_tags_mv` keys on `coalesce(type, purpose)`. Tags written by the server now also carry the spec `purpose` field (PR #66)
* MongoDB backend tag paths (`getTags`, `saveTags`, `searchByTags`, unique-tag discovery) and `extractTags` recognize either spelling via a shared `isTagsAttachment()` predicate (PR #66)

### Migration

normalizing trigger and backfills existing tag attachments. It deliberately does not rebuild `vcon_tags_mv`, so it is safe to apply out of order

### Notes

* 1.4.0 was tagged but never published to npm; its CHANGELOG entry was clobbered by the #66 merge and is restored below. Installing 1.5.0 from npm brings everything since 1.3.0

## \[1.4.0] - 2026-08-18

> Tagged but never published to npm; superseded by 1.5.0.

### Added

* Supabase-native `gte-small` embeddings, so a hosted dataset needs no third-party embedding key: `embedSupabase()` runs inside the Supabase project at the native 384 dims, `embed-vcons` accepts `supabase` as a provider (and falls back to it instead of erroring on a missing `OPENAI_API_KEY`), and a new `embed-query` edge function embeds query strings with the same model as the corpus. `EMBEDDING_PROVIDER` forces a specific choice (PR #65)

### Fixed

* **MCP over HTTP was unusable after one request.** `startHttpServer` built a single `StreamableHTTPServerTransport` at startup and reused it for every request; in stateless mode the SDK rejects a reused transport, and because `setupHttpMiddleware` never awaited `handleRequest` the rejection surfaced as an empty-body HTTP 500 — so a hosted server accepted exactly one `initialize` per container start. Each request now reuses the transport for its `Mcp-Session-Id` or gets a fresh transport and MCP Server (PR #68)
* Port resolution used `config.port || ...`, so port 0 (bind any free port) fell through to the default (PR #68)
* Tags stored as a flat JSON object body (`{"source": "gmail", ...}`, produced by external ingest) read back as no tags at all, because every read path required the `["key:value", ...]` array form. `vcon_tags_mv` and a new shared `parseTagsBody()` now accept both shapes; writes still emit the array form (PR #67)
* Query-time embedding was hardcoded to `api.openai.com` with no override, so a locally embedded corpus could not be searched at all; the query path now uses the configured provider and rejects a wrong-dimension response instead of passing it into the vector comparison (PR #65)
* `vcon_embeddings` upserts were not idempotent for subject-level rows: `content_reference` is NULL there and Postgres treats NULLs as distinct in a unique constraint, so each backfill pass inserted another full 384-dim copy with no error (PR #65)

### Migration

* `20260817120000_vcon_tags_mv_object_body.sql` — rebuilds `vcon_tags_mv` on `coalesce(type, purpose)` with support for both tag body shapes
* `20260817210000_vcon_embeddings_unique_nulls_not_distinct.sql` — makes the `vcon_embeddings` unique constraint `NULLS NOT DISTINCT`

***

## \[1.3.0] - 2026-06-10

### Added

* Per-group Supabase isolation: an instance is scoped by `SUPABASE_DB_SCHEMA` (default `public`), enabling one MCP server per group via a separate Supabase project (project isolation) or a separate Postgres schema in a shared project (schema isolation) (PR #58)
* `ENV_FILE` support so each instance can load its own `.env.<group>` file
* `VCON_INSTANCE_LABEL` surfaced in startup logs and `GET /api/v1/health` (alongside the active `schema`)
* `start` / `start:group` npm scripts and `scripts/start-group.sh` launcher
* `scripts/bootstrap-schema.sh` (clone `public` into a new schema, with pg version fallback, extension-type preservation, and role grants) and `scripts/migrate-all-groups.sh` (migration fan-out across groups)
* Multi-Supabase Isolation guide; group-isolation env vars documented in installation/configuration/README

### Changed

* MCP server advertises its real package version (was hardcoded `1.0.0`); now sourced from `package.json`
* The Supabase client applies `db.schema` from `SUPABASE_DB_SCHEMA`

***

## \[1.2.0] - 2026-04-15

### Added

* REST API parity with MCP tool surface — full HTTP/JSON access at `/api/v1` (PR #46)
* Predictable vCon contract tools: `vcon_fetch`, `vcon_search`, `vcon_capabilities`, `vcon_taxonomy`, `describe_response_shape`
* HTTP transport (`MCP_TRANSPORT=http`) with Streamable HTTP and SSE
* API-key authentication for REST and MCP HTTP endpoints (`API_KEYS`, `API_KEY_HEADER`, `API_AUTH_REQUIRED`)
* Tool profiles and category controls (`MCP_TOOLS_PROFILE`, `MCP_ENABLED_CATEGORIES`, `MCP_DISABLED_CATEGORIES`, `MCP_DISABLED_TOOLS`)
* Docker image published to `public.ecr.aws/r4g1k2s3/vcon-dev/vcon-mcp` with `main-<sha>`, `latest`, and semver tags
* Build provenance exposed via `X-Version`, `X-Git-Commit`, `X-Build-Time` response headers
* Pino structured JSON logging (stderr); OpenTelemetry instrumentation with OTLP exporter option
* DNS rebinding protection options for HTTP transport (`MCP_HTTP_DNS_PROTECTION`, allowed hosts/origins)
* Discovery surfaces and internal knowledge graph

### Changed

* Tool catalog grew from 30 to 35 (5 new contract tools)
* vCon version handling relaxed to accept any string or missing value
* Dialog disposition validation relaxed to accept any string
* Bearer token extraction tolerates leading whitespace in headers

### Fixed

* Upsert vCon on duplicate UUID submission instead of erroring
* Correct body serialization/deserialization for analysis and attachments (CON-352)
* `getTags` no longer crashes on non-array attachment bodies

***

## \[1.0.1] - 2025-12 (approximate)

> Date precise to the month only — the npm-published 1.0.1 pre-dated the current main lineage and its exact release date isn't in this repo.

### Added

* Comprehensive database documentation for LLMs (architecture, quickstart, schema visual)
* Row Level Security (RLS) support for multi-tenant isolation
* Enhanced database status and analytics scripts
* S3 sync functionality and backfill scripts
* Tenant debugging support
* Versioned resource URIs (vcon://v1/...)
* Backup and restore functionality
* Enhanced embedding generation with backfill options
* Improved database inspection tools

### Changed

* Updated package dependencies
* Enhanced embedding scripts with continuous and backfill modes
* Improved database status reporting with time-ago formatting
* Enhanced dialog, attachment, and analysis type distribution logging

### Fixed

* Removed obsolete test scripts and temporary files
* Improved environment variable management in scripts

***

## \[1.0.0] - 2025-10-14

### Added

#### Core Features

* Full CRUD operations for vCons (create, read, update, delete)
* Component management (parties, dialog, attachments, analysis)
* Advanced search capabilities (metadata, content, semantic, hybrid)
* Tag management system with key-value pairs
* Template-based vCon creation
* Batch operations (import, export, bulk updates)
* Validation and data quality checks
* MCP resources for URI-based access
* MCP prompts for query templates
* Plugin system for extensibility

#### Search & Query

* Metadata search with filters (subject, party, date range)
* Full-text content search with PostgreSQL trigrams
* Semantic search with vector embeddings (pgvector)
* Hybrid search combining keyword and semantic
* Tag-based search and filtering
* Aggregation and statistics

#### Database

* Normalized PostgreSQL schema for vCons
* Full IETF spec compliance (draft-ietf-vcon-vcon-core-00)
* Materialized views for tag queries
* HNSW indexes for vector search
* GIN indexes for full-text search
* Foreign key constraints and referential integrity

#### Developer Features

* TypeScript with full type safety
* Zod schemas for validation
* Comprehensive test suite (Vitest)
* Plugin development framework
* Example plugins and code
* MCP Inspector compatibility

#### Documentation

* Complete user guides
* API reference documentation
* Developer guides (architecture, testing, plugins)
* IETF vCon specification reference
* Database schema documentation
* Migration guides and quick references

### Fixed

#### Specification Compliance

* ✅ Analysis uses `schema` not `schema_version` (Section 4.5.6)
* ✅ Analysis `vendor` is required, not optional (Section 4.5.5)
* ✅ Analysis `body` is string type, not object (Section 4.5.7)
* ✅ Party object includes `uuid` field (Section 4.2.12)
* ✅ Party object includes `did` field (Section 4.2.6)
* ✅ Dialog includes `session_id`, `application`, `message_id` fields
* ✅ No default values for `encoding` fields
* ✅ Dialog `type` has proper CHECK constraint
* ✅ vCon includes `extensions` and `must_support` arrays

### Technical Details

#### Dependencies

* `@modelcontextprotocol/sdk` ^0.4.0
* `@supabase/supabase-js` ^2.39.0
* `zod` ^3.22.4
* `typescript` ^5.3.3
* `vitest` ^1.2.0

#### Requirements

* Node.js 18.x or higher
* PostgreSQL 15.x or higher
* Supabase (local or cloud)

#### Database Schema Version

* Version: 1.0.0
* vCon spec compliance: 0.3.0 (draft-ietf-vcon-vcon-core-00)

***

## \[0.9.0] - 2025-10-07 (Beta)

### Added

* Initial beta release
* Basic CRUD operations
* Search functionality
* Tag system implementation
* Database schema design

### Known Issues

* Documentation incomplete
* Some edge cases in search not handled
* Performance optimization needed

***

## Development Timeline

### Phase 1: Core Implementation (Completed)

* ✅ Database schema with spec corrections
* ✅ CRUD operations with validation
* ✅ Basic search functionality
* ✅ Tag management system
* ✅ MCP protocol integration

### Phase 2: Advanced Features (Completed)

* ✅ Semantic search with embeddings
* ✅ Hybrid search
* ✅ Plugin system
* ✅ Batch operations
* ✅ Template system

### Phase 3: Documentation (Completed)

* ✅ User guides
* ✅ API documentation
* ✅ Developer guides
* ✅ Reference documentation
* ✅ VitePress site

### Phase 4: Production & Distribution (Completed in 1.2.0)

* ✅ REST API parity with MCP surface
* ✅ HTTP transport with API-key auth
* ✅ Docker image pipeline to ECR
* ✅ Pino structured logging + OpenTelemetry
* ✅ Multi-tenant RLS

### Phase 5: Predictability & Discovery (Completed in 1.2.0)

* ✅ Contract tools: `vcon_fetch`, `vcon_search`, `vcon_capabilities`, `vcon_taxonomy`, `describe_response_shape`
* ✅ Discovery surfaces and internal knowledge graph

### Phase 6: Future Work (Planned)

* ⏳ Privacy Suite plugin (consent, redaction, PII detection)
* ⏳ Compliance tooling hooks (GDPR, CCPA, HIPAA)
* ⏳ Performance hardening on large corpora

***

## Migration Guides

### Migrating to 1.0.0

If you're upgrading from a pre-1.0 version or another vCon implementation:

1. **Read the Migration Guide:** [MIGRATION\_GUIDE.md](/reference/migration_guide)
2. **Check Field Names:** [QUICK\_REFERENCE.md](/reference/quick_reference)
3. **Update Database:** [CORRECTED\_SCHEMA.md](/reference/corrected_schema)
4. **Run Tests:** Ensure compliance tests pass

**Critical Changes:**

* Analysis uses `schema` not `schema_version`
* Analysis `vendor` is now required
* Analysis `body` is string, not object
* Party includes `uuid` field
* Dialog includes new fields (`session_id`, `application`, `message_id`)

***

## Version Numbering

We follow [Semantic Versioning](https://semver.org/):

* **Major (X.0.0)**: Breaking changes, incompatible API changes
* **Minor (0.X.0)**: New features, backward compatible
* **Patch (0.0.X)**: Bug fixes, backward compatible

### What Triggers Version Bumps

**Major (Breaking):**

* Database schema changes requiring migration
* API changes incompatible with previous versions
* Required configuration changes

**Minor (Features):**

* New tools, resources, or prompts
* New optional features
* Performance improvements
* Documentation enhancements

**Patch (Fixes):**

* Bug fixes
* Security patches
* Documentation corrections
* Performance optimizations without API changes

***

## Release Notes

### v1.0.0 Release Highlights

This first major release represents a production-ready, fully spec-compliant vCon MCP Server with:

* **100% IETF Spec Compliance** - All known specification issues corrected
* **Production-Ready Database** - Normalized schema with proper constraints and indexes
* **Advanced Search** - Keyword, semantic, and hybrid search capabilities
* **Extensible Architecture** - Plugin system for custom functionality
* **Complete Documentation** - User guides, API reference, developer guides
* **Professional Quality** - TypeScript, comprehensive tests, proper error handling

**Perfect for:**

* Production conversation data management
* AI-powered conversation intelligence
* Compliance and archival systems
* Development and research

**Not Included (Proprietary):**

* Privacy Suite (consent management, PII detection)
* Compliance tools (GDPR, CCPA, HIPAA automation)
* Enterprise support

***

## Future Roadmap

The roadmap below reflects work not yet started or in early planning. Concrete shipped versions live in the dated entries above.

### Near-term (post-1.2.0)

* Privacy Suite plugin (consent management, PII detection, redaction)
* Compliance tooling hooks (GDPR, CCPA, HIPAA support patterns)
* Performance hardening on large corpora (cold-start full-text search)

### Longer-term

* Cloud-native deployment patterns and horizontal scaling guidance
* Additional storage backends

***

## Contributing

See [CONTRIBUTING.md](/development/contributing) for how to contribute to this project.

***

## License

### Open Source Core

The vCon MCP Server is released under the MIT License.

### Proprietary Features

Privacy Suite and enterprise features are available under commercial license.

***

## Support

* **Documentation:** <https://vcon-dev.github.io/vcon-mcp/>
* **Issues:** <https://github.com/vcon-dev/vcon-mcp/issues>
* **Discussions:** <https://github.com/vcon-dev/vcon-mcp/discussions>
* **IETF Working Group:** <https://datatracker.ietf.org/wg/vcon/>

***

**Note:** This changelog reflects the development history. Earlier versions (pre-1.0) were development/beta releases not intended for production use.

***

*Last Updated: May 18, 2026*


# Overview

Practical examples and code snippets for using the vCon MCP Server.

## Overview

This section provides real-world examples of:

* Basic CRUD operations
* Search and query patterns
* Plugin development
* System integration
* System instruction assets for Claude and other agents

## Quick Examples

### Create a vCon

```typescript
import { VConQueries } from 'vcon-mcp';
import { createClient } from '@supabase/supabase-js';

const supabase = createClient(url, key);
const queries = new VConQueries(supabase);

const vcon = await queries.createVCon({
  vcon: '0.4.0',
  uuid: crypto.randomUUID(),
  created_at: new Date().toISOString(),
  subject: 'Customer Support Call',
  parties: [
    { name: 'Agent', mailto: 'agent@example.com' },
    { name: 'Customer', tel: '+1-555-0100' }
  ]
});
```

### Search vCons

```typescript
// Keyword search
const results = await queries.searchVConsContent({
  query: 'billing issue refund',
  limit: 10
});

// Tag-based search
const tagged = await queries.searchByTags({
  tags: {
    department: 'support',
    priority: 'high'
  }
});
```

### Add Analysis

```typescript
await queries.addAnalysis(vconUuid, {
  type: 'sentiment',
  vendor: 'OpenAI',
  product: 'GPT-4',
  schema: 'v1.0',
  body: JSON.stringify({
    sentiment: 'positive',
    score: 0.85,
    confidence: 0.92
  }),
  encoding: 'json'
});
```

## Example Categories

### [Basic Operations](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/basic-operations.md)

* Creating vCons
* Reading vCons
* Updating vCons
* Deleting vCons
* Adding components (dialog, analysis, attachments)

### [Search Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/search-examples.md)

* Keyword search
* Semantic search
* Hybrid search
* Tag filtering
* Date range queries
* Complex filters

### [Plugin Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/plugin-examples.md)

* Simple logging plugin
* Access control plugin
* Audit trail plugin
* Custom tool plugin
* Data transformation plugin

### [Integration Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/integration-examples.md)

* Claude Desktop integration
* REST API wrapper
* Webhook integration
* CRM integration
* Real-time updates

### [System Instruction Assets](/examples/system-instruction-assets)

* Long reusable system instruction block
* Short reusable system instruction block
* Compact `CLAUDE.md` version
* Stricter policy-style version

## Use Case Examples

### Contact Center

```typescript
// Record a customer call
const callVCon = await queries.createVConFromTemplate({
  template_name: 'phone_call',
  subject: 'Customer Inquiry',
  parties: [
    { name: 'Agent Smith', mailto: 'smith@company.com', role: 'agent' },
    { name: 'John Doe', tel: '+1-555-1234', role: 'customer' }
  ]
});

// Add transcription
await queries.addAnalysis(callVCon.uuid, {
  type: 'transcript',
  vendor: 'Deepgram',
  body: 'Customer: I have a question about my bill...',
  encoding: 'none'
});

// Add sentiment
await queries.addAnalysis(callVCon.uuid, {
  type: 'sentiment',
  vendor: 'OpenAI',
  body: JSON.stringify({ sentiment: 'neutral', score: 0.5 }),
  encoding: 'json'
});

// Tag for organization
await queries.addTag(callVCon.uuid, 'department', 'billing');
await queries.addTag(callVCon.uuid, 'resolved', true);
```

### Sales Team

```typescript
// Create sales call vCon
const salesCall = await queries.createVCon({
  vcon: '0.4.0',
  uuid: crypto.randomUUID(),
  created_at: new Date().toISOString(),
  subject: 'Enterprise Demo Call',
  parties: [
    { name: 'Sales Rep', mailto: 'rep@company.com' },
    { name: 'Prospect', mailto: 'prospect@client.com' }
  ]
});

// Extract action items
await queries.addAnalysis(salesCall.uuid, {
  type: 'action_items',
  vendor: 'Claude',
  body: JSON.stringify({
    items: [
      { task: 'Send pricing', owner: 'Sales Rep', due: '2025-10-20' },
      { task: 'Schedule followup', owner: 'Sales Rep', due: '2025-10-22' }
    ]
  }),
  encoding: 'json'
});

// Tag for pipeline
await queries.addTag(salesCall.uuid, 'stage', 'demo');
await queries.addTag(salesCall.uuid, 'deal_size', '50000');
```

## Running Examples

```bash
# Clone repository
git clone https://github.com/vcon-dev/vcon-mcp.git
cd vcon-mcp

# Install dependencies
npm install

# Set up environment
cp .env.example .env
# Edit .env with your credentials

# Run example scripts
npx tsx examples/create-vcon.ts
npx tsx examples/search-demo.ts
npx tsx examples/plugin-demo.ts
```

## Next Steps

* Try the [Basic Operations](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/basic-operations.md) examples
* Explore [Search Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/search-examples.md)
* Build your own [Plugin](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/plugin-examples.md)
* See [Integration Examples](https://github.com/vcon-dev/vcon-mcp/tree/main/docs/examples/integration-examples.md)
* Reuse the [System Instruction Assets](/examples/system-instruction-assets)


# System Instruction Assets

Copy-paste instruction assets for clients, agents, and repository guidance that use the `vcon` MCP server effectively.

These variants all encode the same core policy:

* Prefer the redesigned contract tools
* Use discovery-first retrieval
* Treat `attachment.purpose` as canonical
* Treat `attachment.type` as legacy compatibility only
* Use tags only when the classification truly lives in tags

## Long Version

```
You are connected to the `vcon` MCP server for working with IETF vCon data.

Prefer the redesigned contract tools for new work:
- `vcon_capabilities` to discover supported modes, includes, pagination, limits, and byte budgets
- `vcon_taxonomy` for dataset semantics, portal values, dealer-source guidance, and source-of-truth hints
- `vcon_search` for search and listing
- `vcon_fetch` for single-record reads
- `describe_response_shape` if you need to confirm a response contract before using it

Use a discovery-first strategy:
- If the user wants data that may live in attachments or analysis, discover the live categories first
- For attachments, `purpose` is the canonical spec field
- For attachments, `type` is a legacy compatibility field and should only be used when older data still relies on it
- For analysis, continue using `type`

Prefer MCP resources for simple reads:
- Attachment discovery:
  - `vcon://v1/discovery/attachments/purposes`
  - `vcon://v1/discovery/attachments/types` (legacy compatibility only)
- Analysis discovery:
  - `vcon://v1/discovery/analysis/types`
- Attachment reads:
  - `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}` (preferred)
  - `vcon://v1/vcons/{uuid}/attachments/type/{type}` (legacy compatibility only)
- Analysis reads:
  - `vcon://v1/vcons/{uuid}/analysis/type/{type}`

If you are using the REST API programmatically, follow the same pattern:
- Discover:
  - `GET /api/v1/discovery/attachments/purposes`
  - `GET /api/v1/discovery/attachments/types` (legacy compatibility only)
  - `GET /api/v1/discovery/analysis/types`
- Then read:
  - `GET /api/v1/vcons/:uuid/attachments?purpose={purpose}` (preferred)
  - `GET /api/v1/vcons/:uuid/attachments?type={type}` (legacy compatibility only)
  - `GET /api/v1/vcons/:uuid/analysis?type={type}`

Important behavioral rules:
- Do not jump to tags first for attachment-backed or analysis-backed classifications such as dealer info, summaries, transcripts, QA metadata, or similar fields
- For attachments, prefer `purpose` before `type`
- Use attachment `type` only when working with older or non-spec data
- Use tags only when the classification genuinely lives in the tags attachment
- Keep responses small and predictable: use `include`, `limit`, cursor pagination, metadata-only shapes, and `max_response_bytes` where available
- If you get `RESPONSE_TOO_LARGE`, reduce `include`, lower `limit`, or switch to a lighter response shape and retry

When to use which interface:
- MCP resources are good for direct reads and lightweight discovery
- MCP tools are better for search, pagination, and controlled retrieval
- REST is best for external apps, scripts, and integrations
- Direct Supabase access is best for trusted server-side analytics or bulk workflows, with care around RLS and service-role privileges

Spec compliance rules:
- `analysis.vendor` is required
- `analysis.schema` is correct; do not use `schema_version`
- `attachment.purpose` is the canonical attachment classification field
- `attachment.type` should be treated as legacy compatibility metadata
- `analysis.type` remains the correct classification field for analysis
- Use `mediatype`, not `mimetype`
- Use `critical`, not `must_support`
- Use `amended`, not `appended`
- Respect explicit encoding values when present
```

## Short Version

```
Use the `vcon` MCP server in a discovery-first way.

Prefer:
- `vcon_capabilities`
- `vcon_taxonomy`
- `vcon_search`
- `vcon_fetch`
- `describe_response_shape`

For attachment- or analysis-backed data:
1. Discover categories first
2. Read the matching filtered surface
3. Use tags only if the classification actually lives in tags

Canonical field rules:
- Attachments: prefer `purpose`
- Attachment `type` is legacy compatibility only
- Analysis: use `type`

Preferred MCP resources:
- `vcon://v1/discovery/attachments/purposes`
- `vcon://v1/discovery/analysis/types`
- `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}`
- `vcon://v1/vcons/{uuid}/analysis/type/{type}`

Legacy-only attachment fallback:
- `vcon://v1/discovery/attachments/types`
- `vcon://v1/vcons/{uuid}/attachments/type/{type}`

REST follows the same pattern:
- Discover with `/api/v1/discovery/...`
- Prefer `/api/v1/vcons/:uuid/attachments?purpose=...`
- Use `/api/v1/vcons/:uuid/attachments?type=...` only for legacy data
- Use `/api/v1/vcons/:uuid/analysis?type=...` for analysis

Keep payloads small with `include`, `limit`, pagination, and `max_response_bytes`. If a response is too large, retry with a smaller shape.

Remember:
- `analysis.vendor` is required
- `analysis.schema` is correct
- `attachment.purpose` is canonical
- `attachment.type` is legacy-only
- `analysis.type` is still correct
- `mediatype`, `critical`, and `amended` are the correct field names
```

## CLAUDE.md Version

```
You are connected to the `vcon` MCP server for IETF vCon data. Prefer the redesigned contract tools: `vcon_capabilities`, `vcon_taxonomy`, `vcon_search`, `vcon_fetch`, and `describe_response_shape`. Use a discovery-first approach for attachment- or analysis-backed data. For attachments, `purpose` is the canonical spec field and `type` is legacy compatibility only; for analysis, continue using `type`. Prefer MCP discovery/read surfaces in this order: `vcon://v1/discovery/attachments/purposes`, `vcon://v1/discovery/analysis/types`, `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}`, `vcon://v1/vcons/{uuid}/analysis/type/{type}`. Only use `vcon://v1/discovery/attachments/types` or `vcon://v1/vcons/{uuid}/attachments/type/{type}` when older data still relies on attachment `type`. Do not jump to tags first for dealer info, summaries, transcripts, QA metadata, or other data that may live in attachments or analysis; use tags only when the classification truly lives in the tags attachment. Keep responses small and predictable with `include`, `limit`, pagination, metadata-only shapes, and `max_response_bytes`, and if a response is too large, retry with a smaller shape. Remember the key spec rules: `analysis.vendor` is required, `analysis.schema` is correct instead of `schema_version`, `mediatype` is correct instead of `mimetype`, `critical` replaces `must_support`, and `amended` replaces `appended`.
```

## Policy-Style Version

```
You are connected to the `vcon` MCP server for IETF vCon data.

Required defaults:
- Prefer `vcon_capabilities`, `vcon_taxonomy`, `vcon_search`, `vcon_fetch`, and `describe_response_shape` for new work.
- Use discovery-first retrieval before assuming field locations.
- Keep responses minimal and predictable.

Attachment and analysis policy:
- Treat `attachment.purpose` as the canonical spec field.
- Treat `attachment.type` as legacy compatibility only.
- Treat `analysis.type` as the correct analysis classification field.
- Do not treat attachment `type` and attachment `purpose` as equivalent in new designs.
- Do not prefer attachment `type` when `purpose` can satisfy the request.
- Do not use tags first when the requested data may live in attachments or analysis.
- Use tags only when the classification genuinely lives in the tags attachment.

Preferred MCP read order:
1. `vcon://v1/discovery/attachments/purposes`
2. `vcon://v1/discovery/analysis/types`
3. `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}`
4. `vcon://v1/vcons/{uuid}/analysis/type/{type}`

Legacy-only attachment fallback:
- `vcon://v1/discovery/attachments/types`
- `vcon://v1/vcons/{uuid}/attachments/type/{type}`

REST policy:
- Follow the same discovery-first pattern with `/api/v1/discovery/...`
- Prefer `GET /api/v1/vcons/:uuid/attachments?purpose={purpose}`
- Use `GET /api/v1/vcons/:uuid/attachments?type={type}` only for legacy compatibility
- Use `GET /api/v1/vcons/:uuid/analysis?type={type}` for analysis classification

Response-shaping policy:
- Use `include`, `limit`, pagination, metadata-only shapes, and `max_response_bytes` where available.
- If a response is too large, reduce `include`, reduce `limit`, or choose a lighter shape and retry.
- Prefer direct MCP resources for lightweight reads.
- Prefer tools for search, pagination, and controlled retrieval.

Spec compliance requirements:
- `analysis.vendor` is required.
- `analysis.schema` is correct; do not use `schema_version`.
- `mediatype` is correct; do not use `mimetype`.
- `critical` is correct; do not use `must_support`.
- `amended` is correct; do not use `appended`.

Behavioral rule:
- If the user asks for dealer info, summary-like data, transcript-like data, QA metadata, or any other likely attachment- or analysis-backed classification, you must check purpose/type discovery surfaces before falling back to tags.
```


# Large Database Optimization

This guide shows how to use the vCon MCP Server efficiently with large databases to prevent memory exhaustion and improve performance.

## Problem: Memory Exhaustion with Large Databases

When working with large databases (10,000+ vCons), standard queries can return massive amounts of data that exhaust the LLM's memory. For example:

```typescript
// ❌ BAD: This can return 100+ full vCons and exhaust memory
{
  "query": "what happened last week",
  "limit": 100
}
```

## Solution: Smart Response Formatting and Limits

### 1. Check Database Size First

Before running queries, check the database size to understand the scale:

```typescript
// Get database size and recommendations
{
  "include_recommendations": true
}
```

Response:

```json
{
  "success": true,
  "database_size_info": {
    "total_vcons": 50000,
    "total_size_bytes": 2147483648,
    "total_size_pretty": "2.0 GB",
    "size_category": "very_large",
    "recommendations": {
      "max_basic_search_limit": 10,
      "max_content_search_limit": 25,
      "max_semantic_search_limit": 25,
      "max_analytics_limit": 50,
      "recommended_response_format": "metadata",
      "memory_warning": true
    }
  }
}
```

### 2. Get Smart Limits for Your Query

Get recommended limits based on query type and expected result size:

```typescript
// Get smart limits for content search
{
  "query_type": "content",
  "estimated_result_size": "large"
}
```

Response:

```json
{
  "success": true,
  "smart_limits": {
    "query_type": "content",
    "estimated_result_size": "large",
    "recommended_limit": 20,
    "recommended_response_format": "metadata",
    "memory_warning": true,
    "explanation": "Database has 50,000 vCons (very_large size). For content queries with large results, recommend limit of 20 with metadata format. ⚠️ Memory warning: Large dataset detected."
  }
}
```

### 3. Use Appropriate Response Formats

#### Metadata Format (Recommended for Large Databases)

```typescript
// ✅ GOOD: Returns only essential info
{
  "query": "what happened last week",
  "limit": 20,
  "response_format": "metadata"
}
```

Response:

```json
{
  "success": true,
  "count": 20,
  "response_format": "metadata",
  "results": [
    {
      "uuid": "abc-123-def",
      "subject": "Customer Support Call",
      "created_at": "2024-01-15T10:30:00Z",
      "parties_count": 2,
      "dialog_count": 5,
      "analysis_count": 3,
      "attachments_count": 1
    }
    // ... 19 more metadata records
  ]
}
```

#### IDs Only Format (For Further Processing)

```typescript
// ✅ GOOD: Returns only UUIDs for batch processing
{
  "query": "billing issues",
  "limit": 50,
  "response_format": "ids_only"
}
```

Response:

```json
{
  "success": true,
  "count": 50,
  "response_format": "ids_only",
  "results": [
    "abc-123-def",
    "xyz-456-ghi",
    "def-789-jkl"
    // ... 47 more UUIDs
  ]
}
```

#### Snippets Format (For Content Search)

```typescript
// ✅ GOOD: Returns search snippets with highlights
{
  "query": "refund request",
  "limit": 25,
  "response_format": "snippets"
}
```

Response:

```json
{
  "success": true,
  "count": 25,
  "response_format": "snippets",
  "results": [
    {
      "vcon_id": "abc-123-def",
      "content_type": "dialog",
      "content_index": 2,
      "relevance_score": 0.95,
      "snippet": "Customer called about <mark>refund request</mark> for order #12345..."
    }
    // ... 24 more snippets
  ]
}
```

### 4. Batch Processing for Large Results

When you need to process many results, use IDs-only format and then fetch individual vCons:

```typescript
// Step 1: Get IDs
{
  "query": "last month",
  "limit": 100,
  "response_format": "ids_only"
}

// Step 2: Fetch specific vCons as needed
{
  "uuid": "abc-123-def"
}
```

### 5. Use Analytics Tools for Overview

For understanding patterns without loading individual records:

```typescript
// Get content analytics instead of individual records
{
  "include_dialog_analysis": true,
  "include_party_patterns": true,
  "include_conversation_metrics": true
}
```

## Best Practices

### 1. Always Check Database Size First

```typescript
// Before any large query
get_database_size_info → get_smart_search_limits → search with appropriate limits
```

### 2. Use Metadata Format by Default

```typescript
// Default to metadata for large databases
{
  "response_format": "metadata",
  "limit": 20
}
```

### 3. Use Pagination for Large Results

```typescript
// First page
{
  "query": "customer complaints",
  "limit": 20,
  "response_format": "metadata"
}

// Next page (if needed)
{
  "query": "customer complaints",
  "limit": 20,
  "offset": 20,
  "response_format": "metadata"
}
```

### 4. Use Analytics for Patterns

```typescript
// Instead of loading 1000 records
{
  "query": "billing issues",
  "limit": 1000,
  "response_format": "ids_only"
}

// Use analytics to understand patterns
{
  "include_content_analytics": true,
  "include_tag_analytics": true
}
```

## Response Format Comparison

| Format     | Size                   | Use Case            | Memory Safe      |
| ---------- | ---------------------- | ------------------- | ---------------- |
| `full`     | \~50KB per vCon        | Detailed analysis   | ❌ No (large DBs) |
| `metadata` | \~200 bytes per vCon   | Overview, filtering | ✅ Yes            |
| `snippets` | \~500 bytes per result | Content search      | ✅ Yes            |
| `ids_only` | \~36 bytes per vCon    | Batch processing    | ✅ Yes            |

## Memory Usage Examples

For a database with 50,000 vCons:

* **Full format (100 results)**: \~5MB (❌ Memory exhaustion)
* **Metadata format (100 results)**: \~20KB (✅ Safe)
* **IDs only (100 results)**: \~3.6KB (✅ Very safe)
* **Snippets (100 results)**: \~50KB (✅ Safe)

## Summary

1. **Check database size** before running queries
2. **Use smart limits** based on database size
3. **Default to metadata format** for large databases
4. **Use IDs-only for batch processing**
5. **Use analytics tools** for pattern analysis
6. **Implement pagination** for large result sets

This approach ensures efficient operation with databases of any size while preventing memory exhaustion.


# Thread context bootstrap

Use this file at the start of an optimization thread. It summarizes decisions, behavior, and where assets live.

## Purpose vs type (attachments)

* **`attachment.purpose`** is the **canonical** spec-facing classification field for attachments.
* **`attachment.type`** is **legacy / compatibility only** (e.g. older data, Strolid-style metadata). Do not treat it as equivalent to `purpose` for new designs.
* **`analysis.type`** remains the correct classification field for analysis (unchanged).

### Read / discovery order (preferred)

1. Discover attachment purposes: `vcon://v1/discovery/attachments/purposes` or `GET /api/v1/discovery/attachments/purposes`
2. Discover analysis types: `vcon://v1/discovery/analysis/types` or `GET /api/v1/discovery/analysis/types`
3. Read attachments by purpose: `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}` or `GET /api/v1/vcons/:uuid/attachments?purpose=...`
4. Read analysis by type: `vcon://v1/vcons/{uuid}/analysis/type/{type}` or `GET /api/v1/vcons/:uuid/analysis?type=...`

### Legacy-only attachment paths

* `vcon://v1/discovery/attachments/types` / `GET /api/v1/discovery/attachments/types`
* `vcon://v1/vcons/{uuid}/attachments/type/{type}` / `GET /api/v1/vcons/:uuid/attachments?type=...`

### Tags

* Do **not** jump to tags first for dealer-like, summary-like, transcript-like, or other attachment/analysis-backed data.
* Use tags only when classification **actually** lives in the tags attachment.

## Contract tools (recommended for agents)

Prefer: `vcon_capabilities`, `vcon_taxonomy`, `vcon_search`, `vcon_fetch`, `describe_response_shape`.

Payload discipline: `include`, `limit`, pagination, metadata-only shapes, `max_response_bytes`; on `RESPONSE_TOO_LARGE`, shrink and retry.

## Spec reminders (high signal)

* `analysis.vendor` required; `analysis.schema` not `schema_version`; `body` as string when structured JSON is stored.
* `mediatype` not `mimetype`; `critical` not `must_support`; `amended` not `appended`.

## Code / docs touchpoints (for optimization work)

* Types: `src/types/vcon.ts` (`Attachment.purpose` vs optional `type`).
* MCP resources: `src/resources/index.ts` (discovery + filtered reads; purpose-first descriptions).
* REST: `src/api/routes/discovery.ts`, `src/api/routes/vcons.ts`, mount in `src/api/rest-router.ts`.
* Shared filters: `src/utils/read-surfaces.ts`.
* Query layer: `src/db/interfaces.ts`, `src/db/queries.ts`, `src/db/mongo-queries.ts` (distinct discovery + Supabase `purpose` round-trip on attachments).
* Tool schema: `src/tools/vcon-crud.ts` (`AttachmentSchema` documents purpose vs type).
* Tests: `tests/new-tools-resources.test.ts`, `tests/api/routes/discovery.test.ts`, `tests/api/routes/vcons.test.ts`, `tests/db-queries.test.ts`, `tests/api/helpers.ts`.

## Documentation assets (system instructions)

Full copy-paste variants live in:

* `docs/examples/system-instruction-assets.md` (long, short, CLAUDE.md one-paragraph, strict policy-style)

Linked from:

* `docs/examples/index.md`
* `docs/SUMMARY.md`

## Verification notes

* `npm run build` and targeted Vitest suites were used during implementation.
* `npm run docs:build` succeeded after adding the system-instruction assets page.

***

*This file is intentionally dense so a new thread can load one artifact instead of replaying the whole conversation.*


# Session handoff for vault

## What was implemented (high level)

* **Discovery-first read surfaces** for attachment and analysis categories across **MCP resources** and **REST**.
* **Canonical rule**: `attachment.purpose` is spec-facing; `attachment.type` is **legacy compatibility only**. **`analysis.type`** unchanged.
* **Query layer**: distinct values for attachment types, attachment purposes, analysis types (Supabase + Mongo); Supabase **persists and reads `attachment.purpose`**.
* **Shared helpers**: `src/utils/read-surfaces.ts` (filter, tags extract, discovery value shaping).
* **Docs**: REST + resources + README; **four system-instruction copy-pastes** in `docs/examples/system-instruction-assets.md`; **thread bootstrap** in `docs/optimization/thread-context-bootstrap.md`.

## URIs and REST (cheat sheet)

**MCP discovery**

* `vcon://v1/discovery/attachments/purposes` (preferred)
* `vcon://v1/discovery/attachments/types` (legacy)
* `vcon://v1/discovery/analysis/types`

**MCP filtered reads**

* `vcon://v1/vcons/{uuid}/attachments/purpose/{purpose}` (preferred)
* `vcon://v1/vcons/{uuid}/attachments/type/{type}` (legacy)
* `vcon://v1/vcons/{uuid}/analysis/type/{type}`

**REST**

* `GET /api/v1/discovery/attachments/purposes`
* `GET /api/v1/discovery/attachments/types`
* `GET /api/v1/discovery/analysis/types`
* `GET /api/v1/vcons/:uuid/attachments?purpose=...` (preferred)
* `GET /api/v1/vcons/:uuid/attachments?type=...` (legacy)
* `GET /api/v1/vcons/:uuid/analysis?type=...`

## Key files

| Area                            | Path                                            |
| ------------------------------- | ----------------------------------------------- |
| MCP resource list + resolve     | `src/resources/index.ts`                        |
| REST discovery                  | `src/api/routes/discovery.ts`                   |
| REST vCon reads                 | `src/api/routes/vcons.ts`                       |
| Router mount                    | `src/api/rest-router.ts`                        |
| Filters                         | `src/utils/read-surfaces.ts`                    |
| Types                           | `src/types/vcon.ts`                             |
| IVConQueries                    | `src/db/interfaces.ts`                          |
| Supabase                        | `src/db/queries.ts`                             |
| Mongo                           | `src/db/mongo-queries.ts`                       |
| add\_attachment schema          | `src/tools/vcon-crud.ts`                        |
| Instruction assets (4 variants) | `docs/examples/system-instruction-assets.md`    |
| Optimization bootstrap          | `docs/optimization/thread-context-bootstrap.md` |

## Tests touched / added

* `tests/new-tools-resources.test.ts`
* `tests/api/routes/discovery.test.ts`
* `tests/api/routes/vcons.test.ts`
* `tests/db-queries.test.ts`
* `tests/api/helpers.ts`

## Commands that were green

* `npm run build`
* `npx vitest run` (targeted suites during work)
* `npm run docs:build`

## Policy for agents (one line)

Discover **attachment purposes** and **analysis types** first; read by **`purpose`** for attachments and **`type`** for analysis; use **`attachment.type` only for legacy data**; use **tags** only when data lives in tags.

## Next thread (optimization) — suggested focus

* Performance of distinct-category queries at scale (SQL vs batch fallback).
* Whether to add **write-path normalization** (`type` → `purpose`) on ingest.
* Optional deprecation timeline for attachment-`type` discovery surfaces.

## Checkpoint 2026-05-13 — shape graph, capabilities, tests

**Shipped in repo (local commit, not pushed)**

* **OSS shape graph**: `src/types/vcon-shape-graph.ts`; `getVconShapeGraph()` on `IVConQueries` with Postgres materialization (SQL path + fallback) and Mongo implementation; optional co-occurrence edges where supported.
* **Surfaces**: MCP resource `vcon://v1/graph/shape`; read tool `vcon_graph_shape`; `vcon_capabilities` lists the tool and a `shape_graph` block (resource URI, JSON schema id, short description). `describe_response_shape` includes `vcon_graph_shape`.
* **Docs**: `docs/api/shape-graph-and-plugins.md` (default graph plus how proprietary graphs attach via plugins).
* **Tests**: `tests/handlers/schema.test.ts` and `tests/tools/templates.test.ts` aligned to 0.4.0 and real handler responses (raw JSON Schema for `get_schema`, file body for TypeScript mode); registry and tool-category counts; resource tests for shape graph; stress read for `vcon://v1/graph/shape`.

**Suggested next hardening pass**

* Re-read SQL for `getVconShapeGraph` under tenant RLS and large corpora (timeouts, `exec_sql` availability).
* Optional caching for shape graph (same Redis optional pattern as other queries).
* Contract tests for `SHAPE_GRAPH_FAILED` and oversized payloads if you add strict byte limits later.

***

*Copy this file into your vault, or keep it in-repo and `@` it from the optimization thread.*


