---
doc: MCP App Team Kit
version: 1.0.1
last_updated: 2026-11-15
applies_to: [client, trainer, admin, center, provider]
decisions: [TD-01, TD-02, TD-05, TD-06]
---

# MCP App Team Kit — copy, paste, start

Ready-to-paste setup for the **Flutter** (`client`, `trainer`) and **Vue**
(`admin`, `center`, `provider`) teams so their coding agent reads the Morvia
"brain" (registry, BRD, decisions, feature docs, endpoint catalog) on its own.
Explanations and the full tool list: [MCP_AGENT_GUIDE.md](MCP_AGENT_GUIDE.md).

MCP server name: **`morvia-docs`** (from `APP_NAME=Morvia`; `/docs` on the
backend shows the exact name and URL).

## 1. Get two values from the backend team

| Value | Where it comes from |
|-------|---------------------|
| `MORVIA_MCP_URL` | The backend you are reading this page on. Open this file from **that backend's** `/docs/MCP_APP_TEAM_KIT.md` and every `https://{HOST}/mcp/docs` below is already filled with its real URL (a local backend gives `http://localhost:8000/mcp/docs`). Read it elsewhere (git, raw file)? Replace `{HOST}` yourself. |
| `MORVIA_DOCS_TOKEN` | The server's `DOCS_TOKEN`. Not needed on a local backend (no token set). |

```bash
# ~/.zshrc or ~/.bashrc — skip the token line against a local backend
export MORVIA_MCP_URL="https://{HOST}/mcp/docs"
export MORVIA_DOCS_TOKEN="paste-the-token-here"
```

Never commit the token. Restart the terminal / agent after exporting.

## 2. Connect your agent (pick yours)

### Claude Code (one command)

```bash
claude mcp add --transport http morvia-docs "$MORVIA_MCP_URL" \
  --header "Authorization: Bearer $MORVIA_DOCS_TOKEN"
```

### Claude Code / any `.mcp.json` (commit this, token stays in env)

```json
{
  "mcpServers": {
    "morvia-docs": {
      "type": "http",
      "url": "${MORVIA_MCP_URL}",
      "headers": { "Authorization": "Bearer ${MORVIA_DOCS_TOKEN}" }
    }
  }
}
```

### Cursor — `.cursor/mcp.json`

```json
{
  "mcpServers": {
    "morvia-docs": {
      "url": "${env:MORVIA_MCP_URL}",
      "headers": { "Authorization": "Bearer ${env:MORVIA_DOCS_TOKEN}" }
    }
  }
}
```

### VS Code Copilot — `.vscode/mcp.json`

```json
{
  "inputs": [
    { "id": "morvia-docs-token", "type": "promptString", "description": "Morvia docs token", "password": true }
  ],
  "servers": {
    "morvia-docs": {
      "type": "http",
      "url": "https://{HOST}/mcp/docs",
      "headers": { "Authorization": "Bearer ${input:morvia-docs-token}" }
    }
  }
}
```

### Codex — `~/.codex/config.toml`

```toml
[mcp_servers.morvia-docs]
url = "https://{HOST}/mcp/docs"
bearer_token_env_var = "MORVIA_DOCS_TOKEN"
```

### Gemini CLI — `.gemini/settings.json`

```json
{
  "mcpServers": {
    "morvia-docs": {
      "httpUrl": "https://{HOST}/mcp/docs",
      "headers": { "Authorization": "Bearer $MORVIA_DOCS_TOKEN" }
    }
  }
}
```

Local backend (no `DOCS_TOKEN`): drop the `headers` / `--header` / token lines.

## 3. Verify (30 seconds)

```bash
curl -s "$MORVIA_MCP_URL" \
  -H "Authorization: Bearer $MORVIA_DOCS_TOKEN" \
  -H "Content-Type: application/json" -H "Accept: application/json, text/event-stream" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

A JSON list of 7 tools = server and token are fine. Then ask your agent:

> Call `get-integration-brief` for surface `SURFACE` and show me the result.

## 4. Teach your agent to use the brain (paste once into your app repo)

Put the block in the file your agent reads: `CLAUDE.md` (Claude Code),
`AGENTS.md` (Codex / Antigravity / OpenCode), `.cursor/rules/morvia-backend.mdc`
with `alwaysApply: true` (Cursor), `.github/copilot-instructions.md` (Copilot),
`GEMINI.md` (Gemini CLI). Replace `SURFACE` using the table in §5.

````markdown
## Backend integration (Morvia API) — mandatory

Backend docs are served by the `morvia-docs` MCP server. This app's surface is `SURFACE`.

Before writing or changing any code that calls the Morvia API:
1. Call `get-integration-brief` with surface `SURFACE` and the feature (slug or BRD ID).
   It already holds the registry row, the feature doc's Quick reference, the BRD
   section and the decision rows. Read more only one slice at a time: `read-doc`
   with `outline=true`, then `section="…"`. Read `API_CONVENTIONS.md` and
   `SURFACE/README.md` once per project, not per feature.
2. Call `get-endpoint` for every endpoint the code uses. Build request models
   from its field docs, response models and error handling from the feature
   doc's real responses and error table.
3. When `get-endpoint` returns `variables`, order the calls of a flow from it and
   keep those values in app state. Never hard-code an id or token from an example.
4. Integrate only features whose status is `ready` in `PROJECT_BRAIN.md`.
5. Never invent endpoints, fields, enum values or error codes. If the docs do not
   answer it, stop and list it as a question for the backend team.
6. Precedence: `DECISIONS.md` > feature doc > BRD.
7. Do not edit anything under the backend's `docs/`; it is read-only input for you.
8. Done = the feature doc's "Integration checklist" is covered. Finish with the
   docs you read (with versions) and the route names the code calls.
````

Add the stack rules for your tech:

````markdown
<!-- Flutter apps (client, trainer) -->
- Models: one Dart class per response; every documented key exists (missing = `null`).
  Enums arrive as `{value, label}`: branch on `value`, show `label`. Money is a
  2-decimal **string** — parse to a decimal type, never `double`.
- Branch on `data.error_code`, not on message text. Dates are ISO 8601 with offset.
- Show/hide actions from the backend's `can_*` flags.
````

````markdown
<!-- Vue apps (admin, center, provider) -->
- Types: one TypeScript interface per response; every documented key is present.
  Enums arrive as `{value, label}`: branch on `value`. Money is a 2-decimal string.
- Lists use `search`, `filters[...]`, `sort[...]`, `per_page`, `page`; use only the
  ones the feature doc lists. Branch on `data.error_code`.
- Admin permissions are route names (`admin.{group}.{action}`): hide UI from them.
````

## 5. Which surface am I?

| App | Tech | `SURFACE` | Docs folder |
|-----|------|-----------|-------------|
| Trainee app | Flutter | `client` | `docs/client/` |
| Trainer app | Flutter | `trainer` | `docs/trainer/` |
| Admin dashboard | Vue | `admin` | `docs/admin/` |
| Training center dashboard | Vue | `center` | `docs/center/` |
| Hall & event provider dashboard | Vue | `provider` | `docs/provider/` |

A token from one surface is refused on the others (TD-08).

## 6. Daily workflow

Start every feature with one sentence to your agent:

> Use the `morvia-docs` integrate-feature workflow for `SURFACE` `FEATURE`.
> (Claude Code: `/mcp__morvia-docs__integrate-feature` then `SURFACE FEATURE`.)

Handy prompts:

| Need | Ask |
|------|-----|
| What can I build now? | "Call `list-features` for surface `SURFACE` with status `ready`." |
| What changed? | "Read `CHANGELOG.md` rows for `SURFACE` since version X, then the feature doc's Version history." |
| An error code | "`search-docs` for `ERROR_CODE`." |
| A request shape | "`get-endpoint` for route `SURFACE.group.action`." |
| Try a call | Backend console `{HOST}/tester` (Quick Auth demo logins, non-production only). |

Docs change with the backend: re-run the brief when starting a feature and
compare the feature doc's `version` with what your code was built against.

## 7. Troubleshooting

| Symptom | Fix |
|---------|-----|
| 401 "Docs access token required" | Token env var not set in the shell that starts the agent; header must be `Authorization: Bearer <token>`. |
| 404 on `/mcp/docs` | Production server — use dev / staging. |
| Connected, no tools | Restart the agent / reload MCP servers. |
| Agent never calls the tools | §4 block missing from the instructions file; start with the integrate-feature prompt. |
| Feature not `ready` | The brief says so — stop and ask the backend team. |

## Version history

| Version | Date | Summary |
|---------|------|---------|
| 1.0.1 | 2026-11-15 | The docs viewer fills `{HOST}` / the MCP URL with the backend's own URL. |
| 1.0.0 | 2026-11-15 | First version: Morvia-specific copy-paste kit for the Flutter and Vue teams. |
