# QuinkGL MCP Integration

QuinkGL includes built-in support for **MCP (Model Context Protocol)**, enabling AI assistants to monitor and analyze your gossip learning experiments in real-time.

## What is MCP?

MCP (Model Context Protocol) is an open protocol that allows AI assistants (like Claude) to securely connect with external tools and data sources. QuinkGL's MCP integration exposes your gossip learning metrics through standardized tools.

## Quick Start

### 1. Basic Usage (Programmatic)

```python
from quinkgl import GossipNode, PyTorchModel, MetricsCollector, MCPServer

# Create your gossip node
node = GossipNode(
    node_id="alice",
    domain="my-experiment",
    model=PyTorchModel(my_model),
    # ... other config
)

# Create metrics collector and attach to node
collector = MetricsCollector()
collector.attach(node)

# Start MCP server (in a separate task)
server = MCPServer(collector)
await server.start()

# Run your gossip learning
await node.start()
await node.run_continuous(data=my_data)
```

### 2. CLI Usage

QuinkGL provides a CLI command for starting the MCP server:

```bash
# After installing quinkgl
quinkgl-mcp
```

### 3. Claude Desktop Configuration

To use with Claude Desktop, add this to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "quinkgl-monitor": {
      "command": "python",
      "args": ["-m", "quinkgl.mcp.server"]
    }
  }
}
```

Or if installed via pip:

```json
{
  "mcpServers": {
    "quinkgl-monitor": {
      "command": "quinkgl-mcp"
    }
  }
}
```

## Available MCP Tools

| Tool | Description |
|------|-------------|
| `get_nodes` | List all monitored nodes with their current status |
| `get_training_progress` | Get training progress for all or specific nodes |
| `get_accuracy_history` | Get accuracy and loss history per round |
| `get_model_exchanges` | Get records of model weights sent/received |
| `get_network_topology` | Get network topology based on exchanges |
| `analyze_convergence` | Analyze model convergence across the network |
| `get_full_report` | Get complete experiment report as JSON |

## API Reference

### MetricsCollector

The `MetricsCollector` class collects and stores metrics from GossipNode instances.

```python
from quinkgl.mcp import MetricsCollector

collector = MetricsCollector()

# Attach to a node
collector.attach(gossip_node)

# Detach from a node (metrics are kept)
collector.detach(node_id)

# Query methods
collector.get_all_nodes()                    # List of node IDs
collector.get_node_metrics(node_id)          # Full metrics for a node
collector.get_accuracy_history(node_id)      # Accuracy over rounds
collector.get_model_exchanges(node_id)       # Model exchange records
collector.get_network_topology()             # Network graph
collector.get_convergence_analysis()         # Convergence statistics

# Export all data
data = collector.export_json()
```

### MCPServer

The `MCPServer` class implements the MCP protocol.

```python
from quinkgl.mcp import MCPServer

server = MCPServer(metrics_collector)

# Register custom tools
server.register_tool(
    name="my_custom_tool",
    description="A custom monitoring tool",
    input_schema={"type": "object", "properties": {}},
    handler=my_handler_function
)

# Start the server (blocks until stopped)
await server.start()

# Stop the server
server.stop()
```

## Collected Metrics

### Training Metrics
- Round number
- Loss value
- Accuracy
- Samples trained
- Timestamp

### Model Exchanges
- Direction (sent/received)
- Peer ID
- Model size
- Round number
- Associated metrics (loss, accuracy)

### Aggregation Events
- Number of models aggregated
- Contributing peer IDs
- Total sample count

### Peer Events
- Discovery events
- Disconnect events

## Example: Asking AI About Your Experiment

Once connected, you can ask questions like:

> "How is the gossip learning progressing?"

The AI can use the MCP tools to answer:

```
Using get_training_progress and analyze_convergence tools...

📊 **Gossip Learning Progress Report**

**Nodes:**
- alice: Round 5, Accuracy 32.4%, Running ✓
- bob: Round 5, Accuracy 31.8%, Running ✓

**Convergence:**
- Initial avg accuracy: 17.2%
- Current avg accuracy: 32.1%
- Improvement: +14.9%

**Model Exchanges:**
- Total: 10 exchanges
- alice → bob: 5 models sent
- bob → alice: 5 models received

The training is progressing well with consistent improvement
across rounds. Both nodes are converging at similar rates.
```

## Architecture

```
┌─────────────────────────────────────────────────────────────────┐
│                          Your Code                               │
│  ┌─────────────────┐                                            │
│  │   GossipNode    │──── hooks ────┐                            │
│  │  (alice, bob)   │               │                            │
│  └─────────────────┘               ▼                            │
│                           ┌─────────────────┐                   │
│                           │ MetricsCollector│                   │
│                           │  (in-memory)    │                   │
│                           └────────┬────────┘                   │
│                                    │                            │
│                           ┌────────▼────────┐                   │
│                           │   MCPServer     │                   │
│                           │ (stdio protocol)│                   │
│                           └────────┬────────┘                   │
└────────────────────────────────────┼────────────────────────────┘
                                     │
                             ┌───────▼───────┐
                             │  AI Assistant │
                             │   (Claude)    │
                             └───────────────┘
```

## Lifecycle Hooks

The MCP integration uses the following hooks on `ModelAggregator`:

| Hook | Trigger | Data |
|------|---------|------|
| `on_training_complete` | After local training | TrainingResult |
| `on_model_sent` | After sending model | (peer_ids, model_size) |
| `on_aggregation_complete` | After aggregation | AggregatedModel |

These hooks are automatically registered when you call `collector.attach(node)`.
