> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vrin.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP Tool Reference

> Input and output schemas for the two Vrin MCP tools: vrin_query_async and vrin_check_job.

The Vrin MCP server exposes two tools that work as a pair: one to start a query, one to wait for the result.

## `vrin_query_async`

Start a query against the Vrin knowledge base. Returns immediately with a `job_id` that the client must poll with [`vrin_check_job`](#vrin_check_job).

### Input

| Parameter         | Type      | Default     | Description                                                                                                                                        |
| ----------------- | --------- | ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
| `query`           | `string`  | required    | The natural-language question to answer.                                                                                                           |
| `mode`            | `string`  | `"context"` | Response shape. One of `context`, `chat`, `expert`, `brainstorm`, `raw_facts`. See [response modes](/agents#response-modes-when-using-sdk-or-mcp). |
| `depth`           | `string`  | `"basic"`   | Retrieval depth. One of `basic`, `thinking`, `research`. Only applies when `mode="context"`.                                                       |
| `include_sources` | `boolean` | `true`      | Include source document references in the result.                                                                                                  |

### Output

On success:

```json theme={null}
{
  "success": true,
  "job_id": "b4f1a2c6-...-3e9d",
  "status": "working"
}
```

On failure (e.g. bad API key):

```json theme={null}
{
  "success": false,
  "error": "Invalid or expired API key"
}
```

### Behavior

* The tool writes a job record to DynamoDB and invokes a worker Lambda asynchronously. It returns within \~200ms.
* The `job_id` is a UUID. Keep it — you'll need it for `vrin_check_job`.
* Jobs expire one hour after creation.

***

## `vrin_check_job`

Wait for a running query to complete. Long-polls internally for up to 55 seconds per call. Most queries complete inside the first call.

### Input

| Parameter | Type     | Description                              |
| --------- | -------- | ---------------------------------------- |
| `job_id`  | `string` | The UUID returned by `vrin_query_async`. |

### Output — `status: "completed"`

```json theme={null}
{
  "success": true,
  "job_id": "b4f1a2c6-...-3e9d",
  "status": "completed",
  "elapsed_seconds": 42,
  "result": {
    "summary": "ACME Corp reported $50M in Q4 2025...",
    "context": "Facts: ACME.revenue_q4 = $50M (source: earnings_report.pdf)...",
    "facts_count": 12,
    "sources": [
      {"title": "ACME Q4 Earnings", "chunk_id": "c_123", "score": 0.91}
    ],
    "entities": ["ACME Corp", "Jane Smith"]
  }
}
```

The exact fields in `result` depend on the `mode` passed to `vrin_query_async`. `context` mode returns structured facts for an agent to synthesize; `chat` mode returns a finished prose summary.

### Output — `status: "working"`

```json theme={null}
{
  "success": true,
  "job_id": "b4f1a2c6-...-3e9d",
  "status": "working",
  "elapsed_seconds": 55,
  "progress": "Step 5/7: Scoring relevance",
  "message": "VRIN query is still processing (55s elapsed). Call vrin_check_job again — the query will complete soon."
}
```

When you see `working`, **call `vrin_check_job` again with the same `job_id`**. Most queries finish on the first or second call.

### Output — `status: "failed"`

```json theme={null}
{
  "success": false,
  "job_id": "b4f1a2c6-...-3e9d",
  "status": "failed",
  "elapsed_seconds": 91,
  "error": "Upstream LLM timed out"
}
```

Do not retry the same `job_id` on failure — start a new query with `vrin_query_async`.

### Output — `status: "not_found"`

```json theme={null}
{
  "success": false,
  "job_id": "b4f1a2c6-...-3e9d",
  "status": "not_found",
  "error": "Job not found. It may have expired (jobs expire after 1 hour)."
}
```

***

## Canonical polling pattern

```python theme={null}
start = await session.call_tool(
    "vrin_query_async",
    {"query": "What is ACME's Q4 revenue?", "mode": "context"},
)
job_id = json.loads(start.content[0].text)["job_id"]

while True:
    resp = await session.call_tool("vrin_check_job", {"job_id": job_id})
    data = json.loads(resp.content[0].text)

    if data["status"] == "completed":
        return data["result"]
    if data["status"] == "failed":
        raise RuntimeError(data["error"])
    if data["status"] == "not_found":
        raise RuntimeError("Job expired — restart")
    # status == "working" → call again
```

There's no `time.sleep` in that loop. `vrin_check_job` long-polls internally; calling it back-to-back is correct.

***

## Resources

In addition to the two tools, the server exposes two MCP resources that clients can read without a tool call.

### `vrin://stats`

Returns knowledge-base statistics for the authenticated user:

```json theme={null}
{
  "entity_count": 1247,
  "fact_count": 8912,
  "document_count": 63
}
```

### `vrin://config`

Returns server configuration:

```json theme={null}
{
  "server_version": "1.0.0",
  "api_key_type": "standard",
  "infrastructure": "vrin-shared"
}
```

For `vrin_ent_*` keys, `api_key_type` is `"enterprise"` and `infrastructure` reflects the customer's configured deployment.
