MCP Setup & Configuration
Connect Claude Desktop, Claude Code CLI, or the AiDE VS Code plugin to the POD Governance MCP server. Choose Remote Servers UI for instant zero-setup access, or stdio / .mcp.json for a full local development workflow.
Prerequisites
-
Build the MCP server (only needed for stdio / local mode — skip if using Remote Servers UI):
cd src/mcp npm install npm run build # Output: src/mcp/dist/index.js - Generate an MCP Access Token (PAT) — see the section below. This replaces the old raw-JWT approach; PATs are long-lived and individually revocable.
Generating an Access Token
MCP clients authenticate with a Personal Access Token (PAT) — a long-lived, individually revocable credential that acts on behalf of the user who created it (inheriting their role and project access).
Option A — Self-service (recommended for individuals)
-
1Sign in to the portal Click your avatar in the top navigation bar → Profile page (
/profile). -
2Generate Token In the My MCP Access Tokens section, click Generate Token and choose:
- Name — a label to recognise the token later (e.g. "Claude Desktop — my laptop")
- Scope —
read(GET only; safe for dashboards) orwrite(forward, return, submit) - Expiry — 30 / 60 / 90 days, or never
- Client — recorded against every call in the interaction log
-
3Copy the token immediately The
pgmcp_…value is shown once. It is stored only as a SHA-256 hash and cannot be recovered. If you lose it, revoke it and generate a new one. -
4Paste into your client config Use it as
MCP_API_TOKEN(stdio) or paste into the Access Token field (Remote Servers UI).
The token always acts as you. You can revoke any of your own tokens from the same screen at any time.
Option B — Admin-issued (service accounts & oversight)
Use this when issuing tokens for service accounts (shared/non-human identities for team automation or CI/CD pipelines), or when an admin needs to view or revoke any user's token across the entire organisation. Requires the Admin role.
-
1Open Admin Portal → AI Integration → MCP Access Tokens Sign in with an Admin account and navigate to Admin Portal → AI Integration → MCP Access Tokens. The full token list for all users is displayed here.
-
2Click Generate Token and complete all fields The form has the same fields as Option A, plus:
- Owner — select the service account or user identity the token acts as. The token inherits that identity's role and project access.
- Name — a recognisable label (e.g. "CI Pipeline — nightly report")
- Scope —
read(reporting/dashboards) orwrite(forward, return, submit) - Expiry — 30 / 60 / 90 days, or never
- Client — e.g.
ci-pipelineorservice-account
-
3Copy the token immediately The
pgmcp_…value is shown once. Store it in a secret vault (e.g. Azure Key Vault, GitHub Secrets) — it cannot be recovered from the portal after closing. -
4Distribute / inject into the target client For CI/CD pipelines, inject as an environment secret. For a shared team tool, set
MCP_API_TOKENin the deployment config. Never commit the raw value. -
5Monitor and revoke via the Admin portal All calls made with admin-issued tokens appear in Admin Portal → AI Integration → MCP Interaction Log attributed to the Owner identity. Revoke any token at any time — it stops working on the next request.
Comparison: Option A vs Option B
| Option A — Self-service | Option B — Admin-issued | |
|---|---|---|
| Who can create | Any signed-in user | Admin role only |
| Acts as | The creator (always) | Any chosen Owner identity |
| Best for | Individual developer / analyst | Service accounts, CI/CD, shared team tools |
| Where to create | Profile page (avatar → Profile) | Admin Portal → AI Integration → MCP Access Tokens |
| Visible to admin | Yes — admin can revoke | Yes — admin created it |
| Token format | pgmcp_… — same format, same auth path | |
Environment Variables
| Variable | Required | Description | Example |
|---|---|---|---|
MCP_API_BASE_URL |
Yes | Base URL of the POD Governance REST API | http://localhost:3001/api/v1 |
MCP_API_TOKEN |
Yes | MCP Access Token (PAT) generated in the portal — pgmcp_… |
pgmcp_3f9a… |
MCP_CLIENT |
No | Client label recorded in the interaction log (default claude-desktop) |
aide-vscode |
MCP_PORT |
No | If set, run as an HTTP (Streamable HTTP) server on this port instead of stdio | 3100 |
Transports: stdio (default) vs HTTP
The server picks its transport from the environment:
-
stdio (default) — used by Claude Desktop, Claude Code CLI, and the AiDE VS Code plugin.
The client launches
node dist/index.jsand communicates over stdin/stdout. -
HTTP / Streamable HTTP — set
MCP_PORTand the server starts an HTTP listener athttp://localhost:$MCP_PORT/mcp. Use this for web/browser MCP clients that connect over HTTP rather than spawning a process.
# Run the server in HTTP mode locally
cd src/mcp
MCP_PORT=3100 MCP_API_BASE_URL=http://localhost:3001/api/v1 MCP_API_TOKEN=pgmcp_… node dist/index.js
# → POST/GET/DELETE http://localhost:3100/mcp (GET /health for a liveness check)
The HTTP endpoint runs the MCP Streamable HTTP transport in stateless
mode: every POST /mcp is self-contained — the server spins up a fresh instance, handles
the one JSON-RPC message, and returns plain JSON. No Mcp-Session-Id is issued or required,
so clients never have to track a session. GET /mcp and DELETE /mcp return
405 Method Not Allowed (there is no server→client SSE stream and no session to terminate).
Mcp-Session-Id. Behind iisnode (multiple worker processes + app-pool recycles) the worker
that handled initialize often wasn't the one that received the follow-up
tools/call, so the session wasn't found and the server returned
400 Bad Request: no valid session ID. Stateless mode removes that failure mode entirely.
Hosted on Dev / Staging
The CI/CD pipeline deploys the HTTP transport to the Azure VM as an iisnode IIS sub-app:
dist/index.js
standalone with MCP_PORT, or use the stdio transport.
Per-user auth over HTTP
An HTTP client may authenticate as itself by sending its own PAT on each request:
Authorization: Bearer pgmcp_…
The server forwards that token per-request to the REST API, so the call runs as that user —
inheriting their role/project access and attributing correctly in the
MCP Interaction Log. If no Authorization header is present the server
falls back to the shared MCP_API_TOKEN from its environment.
Claude Desktop
Add a pod-governance entry to the mcpServers block in your Claude Desktop config file.
File location:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json - macOS:
~/Library/Application Support/Claude/claude_desktop_config.json - Linux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"pod-governance": {
"command": "node",
"args": ["C:/Projects/ValueLabs/PODGovernance/src/mcp/dist/index.js"],
"env": {
"MCP_API_BASE_URL": "http://localhost:3001/api/v1",
"MCP_API_TOKEN": "pgmcp_YOUR_TOKEN_HERE",
"MCP_CLIENT": "claude-desktop"
}
}
}
}
Restart Claude Desktop after saving the file.
Claude Code CLI
claude mcp add pod-governance \
--env MCP_API_BASE_URL=http://localhost:3001/api/v1 \
--env MCP_API_TOKEN=pgmcp_YOUR_TOKEN_HERE \
--env MCP_CLIENT=claude-code \
-- node /path/to/PODGovernance/src/mcp/dist/index.js
Or add directly to your project's .mcp.json:
{
"mcpServers": {
"pod-governance": {
"command": "node",
"args": ["./src/mcp/dist/index.js"],
"env": {
"MCP_API_BASE_URL": "http://localhost:3001/api/v1",
"MCP_API_TOKEN": "pgmcp_YOUR_TOKEN_HERE",
"MCP_CLIENT": "claude-code"
}
}
}
}
AiDE Plugin — stdio (.vscode/mcp.json)
AiDE reads MCP server configuration from a .vscode/mcp.json file in the
workspace root — separate from claude_desktop_config.json — so the server is automatically
available to every developer who opens the workspace.
-
1Build the MCP server (one-time)
cd src/mcp npm install npm run build # Output: src/mcp/dist/index.js -
2Create
.vscode/mcp.json{ "servers": { "pod-governance": { "type": "stdio", "command": "node", "args": ["${workspaceFolder}/src/mcp/dist/index.js"], "env": { "MCP_API_BASE_URL": "http://localhost:3001/api/v1", "MCP_API_TOKEN": "pgmcp_YOUR_TOKEN_HERE", "MCP_CLIENT": "aide-vscode" } } } }Note${workspaceFolder}is resolved by VS Code to the project root (c:/Projects/ValueLabs/PODGovernance), so the path works for every team member regardless of where they cloned the repo. -
3Generate your MCP Access Token Follow Option A — Self-service above. Use
MCP_CLIENT: "aide-vscode"so your calls are identified separately in the MCP Interaction Log. -
4Commit
.vscode/mcp.json(without the real token) The file is safe to commit with the placeholder value. Each developer replacespgmcp_YOUR_TOKEN_HEREwith their own PAT locally — tokens are never committed to source control.
Pointing to Dev/Staging instead of local
"MCP_API_BASE_URL": "http://vishnuvm.centralindia.cloudapp.azure.com/PODGovernance_Dev/api/v1"
Verifying the connection
After saving .vscode/mcp.json, AiDE will surface the pod-governance server in its tool palette. Ask AiDE:
"List all active cycles for my projects"
"What's this week's Priorities & Achievements summary?"
"Show me the review status for project proj-123"
If the server fails to connect, check the AiDE output panel for the stderr line:
POD Governance MCP server running on stdio. If you see a
401 Authentication failed, generate a new token from your Profile page and
update MCP_API_TOKEN in .vscode/mcp.json.
AiDE Plugin — Remote Servers UI Recommended — no build needed
The AiDE plugin's Remote Servers settings panel connects directly to the hosted MCP
HTTP endpoint — no local node process, no build step, no .vscode/mcp.json
file required.
When to use which approach
Remote Servers UI (this section)
- MCP process runs on VM — already deployed
- No local build or Node.js install needed
- Auth via Bearer token per HTTP request
- ⚠ SSE progress notifications degraded (iisnode)
- Best for: quick access, all 34 tools instantly
.vscode/mcp.json stdio
- MCP process runs locally via
node - Requires
npm run buildfirst - Auth via
MCP_API_TOKENenv var - ✅ Full stdio streaming — all progress events
- Best for: full local development workflow
Steps
-
1Open the Remote Servers panel In the AiDE plugin sidebar, click MCP Servers → select the Remote Servers tab → Add a remote MCP server.
-
2Fill in the formAdd a remote MCP serverpod-governance-devhttp://vishnuvm.centralindia.cloudapp.azure.com/PODGovernance_Dev/mcppgmcp_YOUR_TOKEN — paste token from step 3Streamable HTTP (Recommended) SSE (Legacy)
Field Value Server Name pod-governance-devServer URL http://vishnuvm.centralindia.cloudapp.azure.com/PODGovernance_Dev/mcpAccess Token Your pgmcp_…PAT — see step 3Transport Type Streamable HTTP (Recommended) ← leave as-is -
3Generate your Access Token Follow Option A — Self-service above. Recommended settings:
- Name:
AiDE Plugin Remote - Scope:
write(required to forward / return / submit cycles) - Expiry: 90 days
- Client:
aide-vscode
Copy immediately — thepgmcp_XXXXXXXvalue is shown once only. Paste it into the Access Token field before closing the dialog. - Name:
-
4Click Add Server AiDE connects immediately. All 34 tools, 3 resources, and 3 pre-built prompts appear in the tool palette — no restart needed.
Per-environment Server URLs
Troubleshooting
| Symptom | Fix |
|---|---|
401 Authentication failed |
Token revoked, expired, or mistyped — generate a new PAT from your Profile page |
403 Token is read-only on forward/return/submit |
Generate a write-scope token |
| Server listed but no tools appear | Check the AiDE output panel; verify the health endpoint:
GET …/PODGovernance_Dev/mcp/health |
Available Tools (34)
Cycle Workflow
Ups & Downs Items CRUD
Priorities & Achievements
Reports & Admin
Admin Portal — Projects / PODs / Users admin token
These run under /admin/* and only succeed with an admin or PMO token
— any other token gets a 403. Delete is guarded: a project with active cycles, or a POD with
projects, returns a 409 (deactivate via the matching update tool instead).
Available Resources (3)
| URI | Description |
|---|---|
pods://projects | All projects accessible to the authenticated user |
pods://cycles/{projectId}/active | Active cycle for a project |
pods://cycles/{id} | Full detail for a specific cycle |
Pre-built Prompts (3)
| Prompt | Args | Description |
|---|---|---|
my_pending_cycles | projectId? | List cycles where you are the current reviewer |
week_pa_summary | weekId? | Summarise all Priorities & Achievements submissions for a week |
cycle_review_status | projectId | One-paragraph status brief for the active cycle |
Progress Notifications
The data-heavy read tools (list_cycles, get_cycle, get_reports,
get_audit_log, get_pa_items) emit MCP
notifications/progress updates while they work — a "started" message and a "completed"
message with the record count. This is opt-in per the MCP spec: a client only receives them if it
includes a progressToken in the request _meta. Clients that don't request
progress are unaffected.
Usage Examples
"List all active cycles for project proj-123"
→ list_cycles(projectId: "proj-123", status: "pl_submitted")
"Forward cycle cycle-456 with comment 'Reviewed and approved'"
→ forward_cycle(cycleId: "cycle-456", comment: "Reviewed and approved")
"What are this week's Priorities & Achievements submissions?"
→ get_current_week() → get_pa_items(weekId: )
"Show me the cycle review status for project proj-123"
→ prompt: cycle_review_status(projectId: "proj-123")
Prompt Library — by task
Everything the assistant can do, phrased the way you'd actually ask. Each example shows a
natural-language prompt and the tool call (or chain of calls) it resolves to. The assistant
acts as you — it can only do what your role and token scope allow, and
every call is recorded in the MCP Interaction Log. Write-tools (add_*,
update_*, delete_*, forward_*, return_*,
submit_*, bilateral_*) require a write-scope token.
1. Discover what needs your attention
"Which cycles am I the current reviewer for?"
→ prompt: my_pending_cycles()
"List the projects I have access to"
→ list_projects()
"Show all returned cycles for project proj-123 that need rework"
→ list_cycles(projectId: "proj-123", status: "returned")
"What's the latest cycle for the Acme POD and who has it now?"
→ list_projects() → list_cycles(projectId: , limit: 1) → get_review_chain(cycleId: )
2. Read a cycle in detail
"Open cycle cycle-456 and summarise the ups and downs"
→ get_cycle(cycleId: "cycle-456")
"Just list the items on cycle-456, separated into ups and downs"
→ list_cycle_items(cycleId: "cycle-456")
"Show the full approval chain for cycle-456 with names and timestamps"
→ get_review_chain(cycleId: "cycle-456")
"Who changed what on cycle-456?"
→ get_audit_log(cycleId: "cycle-456")
"Include deleted items too when you list cycle-456"
→ list_cycle_items(cycleId: "cycle-456", includeDeleted: true)
3. Edit Ups & Downs items create / update / delete
"Add an Up to cycle-456: 'Closed the migration two days early'"
→ add_cycle_item(cycleId: "cycle-456", type: "up", text: "Closed the migration two days early")
"Add a Down: 'Staging environment was unstable all week'"
→ add_cycle_item(cycleId: "cycle-456", type: "down", text: "Staging environment was unstable all week")
"Reword item item-9 to 'Onboarded two new engineers'"
→ update_cycle_item(cycleId: "cycle-456", itemId: "item-9", text: "Onboarded two new engineers")
"Remove item item-12 from the cycle"
→ delete_cycle_item(cycleId: "cycle-456", itemId: "item-12")
"Draft my weekly ups and downs for cycle-456 from these notes: …"
→ (assistant proposes items, then) add_cycle_item(…) × N — review before sending
4. Move a cycle through the approval chain
"Forward cycle-456 to the next reviewer"
→ forward_cycle(cycleId: "cycle-456")
"Approve cycle-456 — note 'Numbers look solid, good quarter'"
→ forward_cycle(cycleId: "cycle-456", comment: "Numbers look solid, good quarter")
"Send cycle-456 back to the PM — the client risk needs more detail"
→ return_cycle(cycleId: "cycle-456", comment: "Please expand on the client risk before resubmitting")
"Give me a one-paragraph brief on the active cycle for proj-123 before I decide"
→ prompt: cycle_review_status(projectId: "proj-123")
5. Draft & submit your Priorities & Achievements
"What Priorities & Achievements week are we in?"
→ get_current_week()
"Add my 3 priorities and 3 achievements for this week" (one must be the AiDE priority)
→ get_current_week() → submit_pl_items(weekId: , items: [
{ type: "priority", text: "Ship the billing revamp", category: "delivery" },
{ type: "priority", text: "Adopt AiDE across the POD", category: "ai", isAide: true },
{ type: "priority", text: "Hire one senior engineer", category: "hiring" },
{ type: "achievement", text: "Cut build time by 40%" },
{ type: "achievement", text: "Closed 3 client escalations" },
{ type: "achievement", text: "Mentored 2 juniors to merge" }
])
"Fix a typo in priority item pi-7"
→ update_pa_item(weekId: , itemId: "pi-7", text: "Adopt AiDE across the whole POD")
"Delete achievement item pi-11"
→ delete_pa_item(weekId: , itemId: "pi-11")
(note: the mandatory AiDE priority can be edited but not deleted)
"Submit my Priorities & Achievements for bilateral review"
→ get_current_week() → submit_pa(weekId: )
6. Review your team's Priorities & Achievements (PM / SPOC / POD Owner)
"Summarise every Priorities & Achievements submission for this week"
→ prompt: week_pa_summary()
"Show me just Priya's priorities for this week"
→ get_current_week() → get_pa_items(weekId: , plId: )
"Approve Priya's Priorities & Achievements — 'Strong, AiDE goal is concrete'"
→ bilateral_approve(weekId: , plId: , comment: "Strong, AiDE goal is concrete")
"Return Arun's Priorities & Achievements — achievements need metrics"
→ bilateral_return(weekId: , plId: , comment: "Please quantify the achievements")
7. Reports & audit
"Give me the governance summary report"
→ get_reports(type: "summary")
"Cycle throughput for project proj-123 between Jan and Mar"
→ get_reports(type: "cycles", projectId: "proj-123", from: "2026-01-01", to: "2026-03-31")
"What's our return rate this quarter?"
→ get_reports(type: "return-rate", from: "2026-04-01", to: "2026-06-30")
"Show the weekly Priorities & Achievements category breakdown"
→ get_reports(type: "pa-categories")
"Pull the audit log for cycle-456"
→ get_audit_log(cycleId: "cycle-456")
get_reports types: summary, cycles, trend,
return-rate, pa-weekly, pa-categories, pa-summary.
8. Administer projects, PODs & users admin token
"List every active project in the Core POD"
→ admin_list_projects(podId: , status: "active")
"Create a project 'Acme Migration' in the Core POD with Maya as sales SPOC"
→ admin_list_pods() → admin_list_users(role: "sales_spoc")
→ admin_create_project(name: "Acme Migration", podId: , salesSpocId: )
"Make Raj the delivery SPOC on project proj-123"
→ admin_update_project(projectId: "proj-123", deliverySpocId: )
"Deactivate project proj-123" (safe alternative to delete)
→ admin_update_project(projectId: "proj-123", status: "inactive")
"Spin up a new POD 'Payments' owned by Dilip"
→ admin_create_pod(name: "Payments", podOwnerId: )
"Promote user u-42 to PM and POD owner"
→ admin_update_user(userId: "u-42", roles: ["pm", "pod_owner"])
"Add user u-42 to proj-123 as a PL"
→ admin_set_user_projects(userId: "u-42", memberships: [{ projectId: "proj-123", memberType: "pl" }])
"Invite priya@acme.com as a Project Lead on proj-123"
→ admin_invite_user(email: "priya@acme.com", role: "pl", projectIds: ["proj-123"])
9. End-to-end conversational flows
"Walk my cycle from draft to submitted: add these 3 ups and 2 downs, then forward it"
→ add_cycle_item(…) × 5 → forward_cycle(cycleId: , comment: "Ready for PM review")
"Check if anything's waiting on me, open the first one, and brief me"
→ my_pending_cycles() → get_cycle(cycleId: ) → get_review_chain(cycleId: )
"Build my Priorities & Achievements for the week from last week's plus these changes, then submit"
→ get_current_week() → get_pa_items(weekId: ) → submit_pl_items(…) → submit_pa(weekId: )
"Onboard a new POD: create it, add a project under it, and invite its lead"
→ admin_create_pod(…) → admin_create_project(…) → admin_invite_user(…)
Managing Tokens & Reviewing Activity
| Task | Where |
|---|---|
| Generate / list / revoke your own tokens | Profile page — click your avatar in the top nav (/profile) |
| Issue service-account tokens / manage any user's token | Admin Portal → AI Integration → MCP Access Tokens |
| See what an assistant actually did | Admin Portal → AI Integration → MCP Interaction Log |
| Rotate a token | Generate a new one, update your config, then revoke the old one |
| A leaked token | Revoke immediately — it stops working on the next request |
The interaction log records every token-authenticated call — including reads, writes, reports, and
denied (403) calls — with the identity, tool name, endpoint, status, and duration. The MCP server
sends an X-MCP-Tool header per call so the log shows the semantic tool name
(e.g. forward_cycle) rather than just the HTTP path.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
Authentication failed — check MCP_API_TOKEN (401) |
Token revoked, expired, or mistyped | Generate a new token in the portal and update your config |
Token is read-only (403) on a forward/return/submit |
Token has read scope |
Generate a write-scope token |
Forbidden (403) on a specific cycle |
The owner identity isn't the current reviewer | Use a token owned by the correct user/role |
| Server listed but no tools appear (Remote Servers UI) | MCP server unreachable or iisnode down | Check GET …/PODGovernance_Dev/mcp/health |
Environment URLs
| Environment | MCP Endpoint | API Base URL |
|---|---|---|
| Local dev | http://localhost:3100/mcp |
http://localhost:3001/api/v1 |
| Dev (Azure VM) | …/PODGovernance_Dev/mcp |
…/PODGovernance_Dev/api/v1 |
| Staging (Azure VM) | …/PODGovernance_Staging/mcp |
…/PODGovernance_Staging/api/v1 |
| Production | https:// |
https:// |
Full VM hostname: vishnuvm.centralindia.cloudapp.azure.com