# Integration Standard: MCP Tools in MORPH Workflows

> **Scope:** integration-mcp
> **Layer:** 2
> **Keywords:** mcp, model-context-protocol, mcp-tools, context7, playwright, mcp-client
> **Load When:** an MCP tool is used in any morph-spec phase

**Verified against:** Claude Code MCP tooling — context7, Playwright; GitHub via `gh` CLI; Neon via `neonctl`. Last-verified: 2026-07-08.

---

Reference for using Model Context Protocol (MCP) tools across morph-spec phases. Each phase benefits from different MCPs depending on what data is needed.

## MCP Availability Detection

Before using any MCP tool, check if it's available in the current session:

```javascript
// Pattern: Attempt the call — if the tool doesn't exist, Claude Code will report it
// There is no "list MCPs" command; just try the most common operation

// GitHub — o morph-spec NÃO usa MCP do GitHub: use o `gh` CLI via Bash
// gh repo view --json name,defaultBranchRef,languages

// Context7 (library docs)
await mcp__context7__resolve_library_id({ libraryName: "react" });

// Playwright (browser automation)
await mcp__playwright__browser_navigate({ url: "https://example.com" });

// Neon — use `neonctl` CLI + `psql`
// neonctl connection-string → get DB URL
// psql <DB_URL> -c "SELECT ..."
```

**Fallback rule:** If an MCP is not available, every phase has a manual alternative using Claude Code native tools (Read, Grep, Glob, Bash).

---

## MCP Providers by Phase

### Phase 1 (Setup) — Project Discovery

| Tool | Use Case | Example |
|------|----------|---------|
| **GitHub CLI (`gh`)** | Repo info, recent PRs, issues | `gh repo view --json ...` (Bash) |
| **Filesystem** | Scan project structure | Native Glob/Read preferred |

```bash
# Detect project type from repo metadata (gh CLI via Bash — sem MCP)
gh repo view --json name,defaultBranchRef,languages,repositoryTopics
gh pr list --limit 10 --json title,state,updatedAt
gh issue list --limit 10 --json title,labels

# Fallback: use Glob to detect stack
# Glob: "**/{package.json,*.csproj,*.sln,go.mod,Cargo.toml}"
```

### Phase 2 (UI/UX) — Design References

| MCP | Use Case | Example |
|-----|----------|---------|
| **Playwright** | Navigate, screenshot, inspect live pages | `mcp__playwright__browser_navigate({ url })` |
| **Context7** | Component library documentation | `mcp__context7__query_docs({ libraryId, query })` |

```javascript
// Screenshot existing app for design reference
await mcp__playwright__browser_navigate({ url: "https://app.example.com/dashboard" });
const screenshot = await mcp__playwright__browser_take_screenshot();
// → Visual reference for UI/UX design

// Inspect page structure via accessibility tree
const snapshot = await mcp__playwright__browser_snapshot();
// → Structured element tree (headings, buttons, inputs, etc.)

// Test responsive layout
await mcp__playwright__browser_resize({ width: 375, height: 812 });
const mobileScreenshot = await mcp__playwright__browser_take_screenshot();

// Get MudBlazor component docs for UI specs
const libId = await mcp__context7__resolve_library_id({
  libraryName: "mudblazor",
  query: "data grid with sorting and filtering"
});
const docs = await mcp__context7__query_docs({
  libraryId: libId,
  query: "DataGrid component props and events"
});

// Fallback: WebSearch for component documentation
// WebFetch for specific component API pages
```

### Gemini Image MCP — AI Image Generation

> Available in: **UI/UX** (preview generation), **Implement** (production assets)

| Tool | Use Case | Example |
|------|----------|---------|
| `generate_image` | Create new image from text prompt | `mcp__gemini-image-mcp__generate_image({ prompt, aspectRatio, outputPath })` |
| `edit_image` | Modify existing image | `mcp__gemini-image-mcp__edit_image({ imageSource, prompt })` |
| `continue_editing` | Iterate on last generated/edited image | `mcp__gemini-image-mcp__continue_editing({ prompt })` |
| `list_images` | Browse image generation history | `mcp__gemini-image-mcp__list_images({ type: "all" })` |
| `get_image_info` | Get metadata about a specific image | `mcp__gemini-image-mcp__get_image_info({ imageId })` |

```javascript
// Generate a hero image using design system tokens
// Read design-system.md first to get project colors and aesthetic direction
const image = await mcp__gemini_image_mcp__generate_image({
  prompt: "A floating tablet showing a modern dashboard interface on a dark charcoal background with copper and gold accent lighting. Premium luxury aesthetic, photorealistic, cinematic lighting with warm rim light.",
  aspectRatio: "16:9",
  outputPath: "public/images/my-feature/hero-mockup.png"
});

// Edit an existing image (keep edits short and targeted)
await mcp__gemini_image_mcp__edit_image({
  imageSource: "public/images/my-feature/hero-mockup.png",
  prompt: "Make the lighting warmer and add a subtle copper glow around the tablet edges."
});

// Iterate with continue_editing (one change at a time)
await mcp__gemini_image_mcp__continue_editing({
  prompt: "More contrast in the shadows."
});

// Fallback: Manual image creation, stock photos, or placeholder divs
```

**Use cases by phase:**

| Phase | Use Case | Tool |
|-------|----------|------|
| UI/UX (2) | Generate preview images for design approval | `generate_image` |
| Implement (7) | Generate production assets from assets.md specs | `generate_image` + `edit_image` |
| Implement (7) | Iterate on generated images for quality | `continue_editing` |

> **Standard:** See `frontend/design-system/ai-image-generation.md` for prompt engineering patterns, aspect ratio guide, and `assets.md` format.

---

### Phase 3 (Design) — Schema & Architecture

| Tool | Use Case | Example |
|------|----------|---------|
| **Neon CLI (`neonctl`) / psql** | Database schema, tables, relationships, RLS | `psql <DB_URL> -c "SELECT ..."` |
| **Context7** | Library docs for architecture decisions | `mcp__context7__query_docs()` |
| **GitHub CLI (`gh`)** | Check existing code patterns, PRs | `gh search code` (Bash) |

```bash
# === SCHEMA ANALYSIS (Critical for contracts.cs) ===

# 0. Get Neon DB connection string
neonctl connection-string
# → e.g.: postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/neondb?sslmode=require

# 1. List all tables
pg_dump $(neonctl connection-string) --schema-only --schema public 2>/dev/null | grep "CREATE TABLE"

# 2. Get schema for each relevant table
psql $(neonctl connection-string) -c "SELECT column_name, data_type, is_nullable, column_default \
  FROM information_schema.columns WHERE table_name = 'leads' ORDER BY ordinal_position"

# 3. Get foreign key relationships
psql $(neonctl connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table, \
  ccu.column_name AS foreign_column FROM information_schema.table_constraints tc \
  JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name \
  JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name \
  WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = 'leads'"

# 4. Check RLS policies (security-critical)
psql $(neonctl connection-string) -c "SELECT tablename, policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
```

**Fallback (Neon database not accessible):**
```
1. Grep: "\.from\(|\.select\(|SELECT |DbSet<" → find query files
2. Read each query file → extract table/column names
3. Glob: "src/**/types/**/*.ts" or "**/Entities/**/*.cs" → find type definitions
4. Read type files → map properties to database columns
```

### Phase 4 (Clarify) — Validation & Research

| MCP | Use Case | Example |
|-----|----------|---------|
| **Context7** | Verify library capabilities, API limits | `mcp__context7__query_docs()` |
| **GitHub CLI (`gh`)** | Check issue discussions, known limitations | `gh search issues` (Bash) |

```javascript
// Verify if library supports a required feature
const docs = await mcp__context7__query_docs({
  libraryId: "/mudblazor/mudblazor",
  query: "DataGrid server-side pagination with virtual scrolling"
});
// → Confirms capability or identifies limitation for spec update

// Fallback: WebSearch for library capabilities
```

### Phase 6 (Tasks) — Planning & Organization

| Tool | Use Case | Example |
|------|----------|---------|
| **GitHub CLI (`gh`)** | Create issues from tasks, link to milestone | `gh issue create` (Bash) |
| **Context7** | Estimate complexity based on library docs | `mcp__context7__query_docs()` |

```bash
# Create GitHub issues from tasks.json (if team uses GitHub Projects)
# — one `gh issue create` per task, iterating tasks.json:
gh issue create --title "T001: Create Entity Lead" \
  --body "description + doneCriteria da task" \
  --label "backend" --milestone "feature-x"
```

### Phase 7 (Implement) — Build & Deploy

| Tool | Use Case | Example |
|------|----------|---------|
| **Neon CLI (`neonctl`) / psql** | Run migrations, create RLS policies | `dotnet ef database update` |
| **GitHub CLI (`gh`)** | Create PR, push branches | `gh pr create` (Bash) |
| **Context7** | Look up API usage during coding | `mcp__context7__query_docs()` |
| **Playwright** | Smoke test deployed features, verify UI | `mcp__playwright__browser_navigate()` |
| **Vercel** | Deploy, check logs, manage env vars | `mcp__vercel__list_projects()` |
| **Azure CLI** | Resource management, deployments | `az` commands |
| **Docker CLI** | Build, run, compose, logs (local) | `docker` commands |

```bash
# === NEON (Migrations & RLS via EF Core) ===

# Create migration
dotnet ef migrations add AddStatusToLeads

# Apply migration to Neon database
dotnet ef database update

# Verify schema after migration
psql $(neonctl connection-string) -c "SELECT column_name, data_type FROM information_schema.columns WHERE table_name = 'leads'"

# Verify RLS policies
psql $(neonctl connection-string) -c "SELECT policyname, cmd, qual FROM pg_policies WHERE tablename = 'leads'"
```

```javascript
// Lookup API during implementation
const docs = await mcp__context7__query_docs({
  libraryId: "/dotnet/efcore",
  query: "owned entity types configuration"
});

// Smoke test deployed feature via browser
await mcp__playwright__browser_navigate({ url: "https://localhost:5001/leads" });
const snapshot = await mcp__playwright__browser_snapshot();
// → Verify page renders correctly, check for errors

// Check for console errors after deploy
const logs = await mcp__playwright__browser_console_messages();
// → Catch JavaScript errors, failed API calls

// Screenshot for recap.md documentation
const screenshot = await mcp__playwright__browser_take_screenshot();

// === VERCEL (Deployment & Environment) ===

// List projects
const projects = await mcp__vercel__list_projects();

// Check deployment status and logs
const deployments = await mcp__vercel__get_deployments({ projectId: 'my-project' });
const logs = await mcp__vercel__get_deployment_logs({ deploymentId: deployments[0].uid });

// Manage environment variables
await mcp__vercel__manage_env_vars({
  projectId: 'my-project',
  action: 'set',
  key: 'DATABASE_URL',
  value: process.env.DATABASE_URL,
  target: ['production', 'preview']
});

// PRs/issues: sempre `gh` CLI (Bash). Deployments fallback: vercel CLI
```

---

## MCP vs Native Tools Decision

| Need | MCP Tool | Native Alternative |
|------|----------|--------------------|
| Database schema | Neon CLI (`neonctl`) / psql | Grep queries + Read types |
| Repo metadata / issues / PRs | Bash `gh` CLI | WebFetch `api.github.com` (read-only) |
| Library docs | Context7 | WebSearch + WebFetch |
| Live page preview | Playwright MCP | WebFetch URL |
| Page interaction (click, type, navigate) | Playwright MCP | Manual testing |
| Responsive layout testing | Playwright MCP (`browser_resize`) | Manual testing |
| Console error checking | Playwright MCP (`browser_console_messages`) | Browser DevTools |
| Container ops | Docker CLI (`docker ps`, `docker logs`, `docker compose`) | — |
| Cloud resources | Azure CLI (`az resource`, `az deployment`) | — |
| Vercel deployments | Vercel MCP | Bash `vercel` CLI |
| AI image generation | Gemini Image MCP | Manual creation or stock photos |

**Rule:** MCP tools provide structured data (JSON responses). Native tools require manual parsing. **Always prefer MCP when available** — fall back to native when not. **Exceptions:** Neon, Docker, Azure **and GitHub** always use their respective CLIs directly — never MCP (`gh` já retorna JSON estruturado via `--json`, sem Docker nem PAT em env var).

---

## Common MCP Patterns

### Browser (Playwright): Page Automation & Analysis

```javascript
// === SETUP ===
// Playwright MCP: npx @playwright/mcp@latest
// Config in .claude/settings.json or claude_desktop_config.json:
// { "mcpServers": { "playwright": { "command": "npx", "args": ["@playwright/mcp@latest"] } } }

// === NAVIGATION & SNAPSHOT ===

// 1. Navigate to a page
await mcp__playwright__browser_navigate({ url: "https://app.example.com/dashboard" });

// 2. Take accessibility snapshot (preferred — structured, LLM-friendly)
const snapshot = await mcp__playwright__browser_snapshot();
// → Returns accessibility tree with element refs for interaction

// 3. Take visual screenshot (requires --caps vision)
const screenshot = await mcp__playwright__browser_take_screenshot();
// → Returns PNG image of current page

// === INTERACTION ===

// 4. Click an element (use ref from snapshot)
await mcp__playwright__browser_click({ element: "Submit button", ref: "s1e15" });

// 5. Type into an input field
await mcp__playwright__browser_type({ element: "Search input", ref: "s1e8", text: "query" });

// 6. Fill a form field (replaces existing value)
await mcp__playwright__browser_fill_form({ ref: "s1e8", value: "new value" });

// 7. Select dropdown option
await mcp__playwright__browser_select_option({ element: "Status", ref: "s1e12", values: ["active"] });

// 8. Press keyboard key
await mcp__playwright__browser_press_key({ key: "Enter" });

// === TABS & NAVIGATION ===

// 9. List open tabs
const tabs = await mcp__playwright__browser_tabs();

// 10. Navigate back
await mcp__playwright__browser_navigate_back();

// 11. Close current tab
await mcp__playwright__browser_close();

// === ADVANCED ===

// 12. Evaluate JavaScript in page context
const result = await mcp__playwright__browser_evaluate({
  expression: "document.querySelectorAll('.error').length"
});

// 13. Get console messages (debug)
const logs = await mcp__playwright__browser_console_messages();

// 14. Get network requests
const requests = await mcp__playwright__browser_network_requests();

// 15. Handle dialog (alert, confirm, prompt)
await mcp__playwright__browser_handle_dialog({ accept: true });

// 16. Resize viewport
await mcp__playwright__browser_resize({ width: 375, height: 812 }); // iPhone viewport

// 17. Save page as PDF (requires --caps pdf)
await mcp__playwright__browser_pdf_save();

// 18. Upload file
await mcp__playwright__browser_file_upload({ ref: "s1e20", paths: ["/path/to/file.png"] });
```

**Use cases by phase:**

| Phase | Use Case | Tool |
|-------|----------|------|
| UI/UX (2) | Screenshot reference pages for design | `browser_navigate` + `browser_take_screenshot` |
| UI/UX (2) | Inspect existing app structure | `browser_navigate` + `browser_snapshot` |
| UI/UX (2) | Test responsive layouts | `browser_resize` + `browser_take_screenshot` |
| Clarify (4) | Verify existing UI behavior | `browser_navigate` + `browser_snapshot` |
| Implement (7) | Smoke test deployed features | `browser_navigate` + `browser_click` + `browser_snapshot` |
| Implement (7) | Verify form flows end-to-end | `browser_fill_form` + `browser_click` + `browser_snapshot` |
| Implement (7) | Check console errors after deploy | `browser_navigate` + `browser_console_messages` |
| Implement (7) | Screenshot for recap.md | `browser_take_screenshot` |

---

### Neon: Full Schema Discovery (via neonctl + psql)

> **Primary:** Neon CLI (`neonctl`) + psql connecting to Neon database.
> **Connection:** Always use `neonctl connection-string` to get the DB URL.

```bash
# Complete workflow for Phase 3 schema analysis

# 1. Get Neon DB URL
neonctl connection-string  # → pooled connection string

# 2. List all tables
pg_dump $(neonctl connection-string) --schema-only --schema public 2>/dev/null | grep "CREATE TABLE"

# 3. For each relevant table:
psql $(neonctl connection-string) -c "SELECT column_name, data_type, is_nullable, column_default \
  FROM information_schema.columns WHERE table_name = 'TABLE_NAME' ORDER BY ordinal_position"

# 4. Get relationships
psql $(neonctl connection-string) -c "SELECT tc.table_name, kcu.column_name, ccu.table_name AS foreign_table \
  FROM information_schema.table_constraints tc \
  JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name \
  JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name \
  WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_name = 'TABLE_NAME'"

# → Write findings to schema-analysis.md
```

### Context7: Library Research

```javascript
// Workflow for any phase needing library documentation
// Step 1: Resolve library ID
const lib = await mcp__context7__resolve_library_id({
  libraryName: "fluent-ui-blazor",
  query: "dialog component with form validation"
});

// Step 2: Query specific documentation
const docs = await mcp__context7__query_docs({
  libraryId: lib.id,
  query: "FluentDialog component usage with EditForm validation"
});
```

### GitHub: Code Search Across Repo (`gh` CLI — sem MCP)

O morph-spec **não instala nem usa MCP do GitHub**. O `gh` CLI (autenticado uma vez via `gh auth login`) cobre a mesma superfície com JSON estruturado, sem Docker e sem PAT em variável de ambiente:

```bash
# Find patterns in large codebase during Phase 2
gh search code "DbSet leads" --repo myorg/myrepo --json path,textMatches
# → Find all places that query the leads table

# Qualquer endpoint REST sem subcomando dedicado:
gh api repos/{owner}/{repo}/branches --jq '.[].name'
```

---

## Security Considerations

- **Never pass secrets** in MCP tool parameters (API keys, tokens, passwords)
- **Neon** uses neonctl/psql — use database branches for development, not production
- **GitHub via `gh` CLI** herda as permissões do login do `gh auth login` (keyring) — sem PAT em env var, sem Docker
- **Always validate tool responses** before using in contracts or code generation

---

*MORPH-SPEC by Polymorphism Tech*
