Teak provides a remote MCP server at `https://teakvault.com/mcp`.

> The MCP server moved from `api.teakvault.com/mcp` to `teakvault.com/mcp`.
> Existing connections keep working — see the [API migration notice](./api#base-urls) for details.

## Base URLs

- Production: `https://teakvault.com/mcp`
- Local development: `http://docs.teak.localhost:1355/mcp`
- Legacy production: `https://api.teakvault.com/mcp`
- Discovery manifest: `https://teakvault.com/.well-known/mcp.json`

## Authentication

Teak's MCP server supports two authentication methods.

### Browser sign-in (recommended)

Spec-compliant MCP clients authenticate with a browser-based OAuth flow. On first connect, the client discovers Teak's authorization server, opens your browser to sign in, and stores the resulting access token automatically. Access tokens are short-lived (1 hour) and refresh automatically.

For example, with Claude:

```bash
claude mcp add --transport http teak https://teakvault.com/mcp
```

Then start the MCP connection (for example, run `/mcp` in Claude) and complete the browser sign-in when prompted.

### API key

You can also authenticate with a Teak API key in the `Authorization` header:

```bash
Authorization: Bearer teakapi_secret_live_a1b2c3d4_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

Generate and manage API keys in Teak Settings: `https://app.teakvault.com/settings`.

Unauthenticated requests receive `401` with a `WWW-Authenticate` header pointing to the OAuth protected-resource metadata at `https://teakvault.com/.well-known/oauth-protected-resource/mcp`, which clients use to begin the browser sign-in flow.

## Transport

- Protocol: MCP Streamable HTTP
- Endpoint path: `/mcp`
- Also supported: `/mcp/`
- Server mode: stateless JSON response mode

OAuth protected-resource discovery advertises the canonical production endpoint
shown above, so MCP clients validate and connect to the same public resource.

## Available Tools

### Core card tools

- `teak_v1_list_cards`
  - Input: `{ limit?: number, cursor?: string, type?: string, favorited?: boolean, tag?: string, sort?: "newest" | "oldest", createdAfter?: number, createdBefore?: number }`
  - Output: `{ items: Card[], pageInfo: { hasMore: boolean, nextCursor: string | null } }`
- `teak_v1_get_card`
  - Input: `{ cardId: string }`
  - Output: full card object
- `teak_v1_create_card`
  - Input: text/URL fields or uploaded-file fields `{ fileKey, fileEtag?, fileName, mimeType, fileSize?, cardType? }`. Pass the `ETag` response header from the upload PUT as `fileEtag` so Teak can verify the exact stored object. Explicit `cardType: "text"` stores raw Markdown exactly; automatic URL, quote, and palette detection remains when the type is omitted.
  - Output: `{ status: "created", cardId: string, appUrl: string }`
- `teak_v1_list_tags`
  - Input: `{}`
  - Output: `{ items: { name: string, count: number }[] }`
- `teak_v1_get_card_changes`
  - Input: `{ since: number, cursor?: string, limit?: number }`
  - Output: `{ items: Card[], deletedIds: string[], pageInfo: { hasMore: boolean, nextCursor: string | null } }`
- `teak_v1_bulk_cards`
  - Input: `{ operation: "create" | "update" | "favorite" | "delete", items: object[], confirm?: true }`
  - Output: bulk operation results; delete batches require `confirm: true`
- `teak_v1_create_upload`
  - Input: `{ fileName: string, mimeType: string, fileSize: number }`
  - Output: `{ uploadUrl: string, fileKey: string, method: "PUT", maxFileSize: number, expiresIn: number }`
  - Supports the same upload matrix as the web app, API, and CLI. `.md` and `.markdown` files become editable text cards and must be valid UTF-8 no larger than 512 KiB; other supported files allow up to 100 MB.
- `teak_v1_search_cards`
  - Input: `{ q?: string, limit?: number }`
  - Output: `{ items: Card[], total: number }`
- `teak_v1_list_favorite_cards`
  - Input: `{ q?: string, limit?: number }`
  - Output: `{ items: Card[], total: number }`
- `teak_v1_update_card`
  - Input: `{ cardId: string, content?: string, url?: string, notes?: string | null, tags?: string[] }`
  - Text-card content remains raw Markdown, preserved exactly, with a 512 KiB UTF-8 limit.
  - Output: updated card object
- `teak_v1_set_card_favorite`
  - Input: `{ cardId: string, isFavorited: boolean }`
  - Output: updated card object
- `teak_v1_delete_card`
  - Input: `{ cardId: string, confirm: true }`
  - Output: `{ status: "deleted", cardId: string }`

### ChatGPT connector tools

Teak also exposes the plain `search` and `fetch` tools expected by ChatGPT connectors and Deep Research:

- `search` accepts `{ query: string }` and returns `{ results: [{ id, title, url }] }`.
- `fetch` accepts `{ id: string }` and returns `{ id, title, text, url, metadata }`.

## Error Format

Tool failures are returned as MCP tool errors with this structured shape:

```json
{
  "status": 429,
  "code": "RATE_LIMITED",
  "error": "Too many requests"
}
```

## JSON-RPC Examples

Initialize:

```json
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-06-18",
    "capabilities": {},
    "clientInfo": {
      "name": "my-client",
      "version": "1.0.0"
    }
  }
}
```

List tools:

```json
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}
```

Call `teak_v1_create_card`:

```json
{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "teak_v1_create_card",
    "arguments": {
      "content": "https://teakvault.com"
    }
  }
}
```