Skip to content

Skills · ai-engineering

mcp-pairing

Recommend which MCP servers to connect for a loop, workflow or task, stage by stage, with the narrowest access that works — what outside context or action each stage needs, the server that provides it (only ones the user named or the vendor officially publishes), the scopes to grant (read-only by default, never write on a review or gate stage), what it must not be able to do, the export-file fallback that keeps the stage running without it, and which stages need no server at all. Use when the user asks "which MCP servers should we hook up for this loop", "what should our agent connect to", "what token scopes does this stage need", "is this MCP setup too broad", or wants to wire GitHub, GitLab, Jira, Linear, Slack, Sentry, Grafana or a database into an agent workflow.

Pack ai-engineeringTier standardJob Design the systemv0.1.0

npx skilldrop-cli install mcp-pairing
Other ways to install

With the sibling skills it hands off to:

npx skilldrop-cli install mcp-pairing --with-related

The whole pack it belongs to:

npx skilldrop-cli install --pack ai-engineering

By hand, from a clone of the repo:

cp -R packs/ai-engineering/skills/mcp-pairing ~/.claude/skills/

In Claude Code, with the ai-engineering plugin installed, invoke it as:

/ai-engineering:mcp-pairing

Try it

A realistic prompt from the skill's acceptance evals:

Which MCP servers should we hook up for our release loop? We use GitLab, Linear and Grafana. The loop is plan the rollout, check launch readiness, write the release notes, then a go/no-go call. We release about every two weeks.

What a good result looks like

Example output

the build loop on GitHub, Jira and Datadog · the skill's own worked example, source

Input

We're adopting the build loop for the orders-api repo. We use GitHub for code and PRs, Jira (project ORD) for stories and bugs, and Datadog for logs and APM. Which MCP servers should we connect, and with what access? We'd like the agent to open the PR itself if that's sensible. About one bug a week needs logs; stories come in daily. Outside contractors open PRs too.

Output

MCP pairing — build loop for orders-api

Tools in use: GitHub, Jira (project ORD), Datadog · Assumptions: the developer's checkout is local, so implement needs no repo server [assumption]; Jira issues in ORD are written by staff and by people raising bugs from support [assumption].

The plan

Connect two servers, both read-only: Jira for the shape stage and GitHub for the verify stage. Implement and decide need none. Datadog is cut: one bug a week is a saved log query, not a live server. Opening the PR is the one write worth granting, on its own GitHub credential used only at the end of implement, and only if the team wants it; otherwise the developer opens the PR.

Pairing by stage

Stage (type, cadence)NeedsServerGrantMust notFallback without itRisk
shape (generate, daily)Tracker issue: the story or bug, its comments and linksAtlassian's own server — confirm Atlassian publishes it in Atlassian's docs before connectingA Jira account with Browse on project ORD only; the server acts with that account's permissionsCreate, transition, comment, assign, edit fields; see any project but ORDThe issue exported from Jira to a text file, or the filter exported as CSVIssue text and comments are untrusted (support-raised bugs). Shape holds no write or exec tool, so reading them is safe here; it writes the story file and nothing else
shape, bugs only (generate, ~weekly)Logs and traces for the failing requestCut — see below——The Datadog log query result saved as JSON, and the trace's spans exported, for the bug's time windowLog lines carry request fields an attacker writes; a file a person picked keeps that bounded
implement (generate, per story)None — works from the story file shape wrote and the local checkoutNone———Implement runs tests (exec) and edits files (write), so it gets no tracker or GitHub server: live issue text next to a shell is the dangerous combination. A person skims the story file before implement starts
implement → open PR (generate, per story, optional)Action: open a draft PR from the pushed branchGitHub's own server, write configuration — confirm GitHub publishes it (GitHub's own organization, docs on GitHub's domain)A separate fine-grained token, orders-api only: Pull requests read and write, Contents read and write; branch protection on main requires reviewMerge, approve, push to main, change settings or branch protection, touch other repositoriesThe developer runs the push and opens the PR by handWrite and exec in one stage, so this stage reads nothing untrusted: no issue comments, no PR comments
verify (verify, per PR)Repo: the PR diff, description, CI statusGitHub's own server in its read-only mode, limited to the repositories, pull requests and Actions toolsetsA separate fine-grained token, orders-api only: Contents read, Pull requests read, Actions readMerge, approve, comment, request changes, label, re-run CIThe diff saved as a .diff file and the PR description copied to a file; the CI summary savedContractor PRs and comments are untrusted, and the gate script is exec. Allow only the gate script command in this session; the verdict goes to a person, never posted by the agent
decide (gate, per PR)None — reads verify's verdict and any design disagreementNone———The merge stays a person's action in GitHub's own UI under their own login

Credentials

VariableServerScopeUsed by stagesKind
None — OAuth sign-in, no stored tokenAtlassianBrowse, project ORDshapeRead
GH_ORDERS_READGitHubContents, Pull requests, Actions: read; orders-apiverifyRead
GH_ORDERS_PR_WRITEGitHubPull requests and Contents: read and write; orders-apiimplement → open PR (optional)Write, separate token

Tokens live in environment variables or the client's secret store. The project's committed MCP config holds variable names only. The write server is a separate server entry, enabled only in the session that opens the PR, so the verify session never loads it.

Servers cut

  • Datadog — needed for about one bug a week. A saved log query and exported trace cover it, with no standing token to the team's logs and no live attacker-written log lines in context. Revisit if bugs needing logs reach several a week.

Check before installing

  • Atlassian's own server — confirm publisher; it acts with the account's own permissions, so the account must have nothing beyond Browse on ORD.
  • GitHub's own server — confirm publisher, use its read-only mode for verify, and turn off every toolset verify doesn't use.

To confirm

  • Whether the team wants the agent to open PRs at all; if not, drop GH_ORDERS_PR_WRITE.
  • That branch protection on main requires an approving review, so even the write token cannot land code alone.

Next step: review the finished setup for any path where issue or PR text could make the agent send private data out, before the first real story runs through it.

How it's checked

Measured against plain Claude Code (2026-10-23): it met 92% of its checks, against 39% without it, and a blind judge preferred it. How skills are checked

39 assertions across 5 acceptance evals, and 10 trigger queries. Every skill's checks

What the output must do
  • It opens with the plan in plain words — how many servers, which ones, read or write, and which stages need none — before any table
  • Every one of the four stages (plan, readiness, release notes, go/no-go) has its own row, including any that get no server
  • No write scope is granted to the readiness check or the go/no-go stage; the go/no-go decision stays with a person
  • Every grant is narrower than 'read-only': a named scope such as GitLab read_api, one project or team, or a Grafana Viewer role, with no admin or api-wide scope
  • Any write (publishing the release or notes) sits on a separate credential used only by the release-notes stage, or is handed to a person
  • It does not invent server names, packages, install commands or URLs the user didn't give; vendor servers are named only as the vendor's own, with how to confirm the publisher
  • Merge request text, comments or Linear issue text are called untrusted, and no stage that reads them is left holding write, exec or network tools
  • Every stage gets an export-file fallback, and at least one server is cut or argued for against the fortnightly cadence
  • It flags the token values written into the config file and says to move them to environment variables or the tool's secret store, with the committed file holding variable names only
  • It drops the admin scopes (admin:org, Slack admin) and the broad repo and workflow scopes, naming the narrower scope each step needs
  • It flags the unpinned community packages (@harbourline/jira-mcp, @harbourline/pg-mcp@latest, @harbourline/slack-mcp) and gives the vetting checks: publisher, source available, pinned version, tools exposed, code or network reach
  • It replaces the app_owner connection to the primary database with a read-only role on a replica, scoped to what the postmortem needs, or with an exported query result
  • It says the Slack posting is the one write the incident-update step's output justifies, on a separate credential from history reading, or hands posting to a person, and the postmortem step gets no write
  • It calls Slack messages and Jira ticket text untrusted and does not leave a step that reads them holding the write or database tools it doesn't need
  • It does not invent replacement package names, URLs or install commands the user didn't give
  • Each step has an export-file fallback, such as the incident channel's thread exported to a file or the query result saved as CSV
  • It answers the question directly in the opening lines, with a clear verdict on the setup as proposed
  • Web pages are called untrusted input, and the stage that browses is not given Notion write or any other write or exec tool in the same session
  • The weigh-the-explanations stage is treated as a verify stage and gets read-only access or none
  • Notion write, if kept at all, goes only to the stage whose output is filing the summary, scoped to the one research space on its own credential; otherwise a person files it
  • Google Drive access is narrowed to the folder of past reports, read-only, or replaced by exported files
  • Given the monthly cadence, at least one server is cut in favour of an export file or saved pages, with the reason stated
  • It does not invent server names, packages or URLs the user didn't give, and names Notion's or Google's server only with how to confirm the publisher
  • Flags the GitHub token (and the Jira/Slack/DB secrets) pasted in plain text in a committed .mcp.json as an immediate problem: says to treat the tokens as exposed and rotate them, and to move secrets out of the file (environment variables or a secret store, referenced instead of stored inline).
  • Flags the classic PAT with admin:org and delete_repo (and workflow) as far too broad, and recommends a narrowly scoped token instead (e.g. a fine-grained token or app limited to example-org/orders-service with only the repository permissions the implement stage needs: contents and pull requests write, plus read for actions/checks).
  • Says the review stage must be read-only: the 'github-reviewer' entry with all toolsets and the ability to approve/merge contradicts the loop's own rule that only a human merges, and should become a read-only connection (diff, CI results, ticket) with no merge, approve, push or write tools.
  • Identifies the Jira server 'jira-mcp-plus-unofficial@latest' and the community Slack/Postgres packages as unknown-origin, unpinned third-party code that gets credentials, and recommends replacing them with the vendor's official server or the user's vetted one (or at minimum pinning and reviewing them), not trusting them as-is.
  • Recommends removing the Postgres connection entirely (or replacing it with a schema-only/read-only path such as a schema dump or migration files), since no stage in the loop needs a database and the current config gives the agent the prod owner role on the orders database.
  • Narrows Slack to what the announce stage actually needs: posting to the single #team-orders-dev channel (chat:write, invited to that channel), dropping history-reading scopes, users:read.email, chat:write.public and admin; and notes that the merge gate stage needs no MCP server at all.
  • Gives a per-stage breakdown (pick up, implement, review, merge gate, announce) stating for each what access it needs, what it must not be able to do, and a fallback if the server is unavailable (e.g. pasted or exported ticket text for pick-up, gh CLI or a saved diff/CI log for review, a human posting the Slack line).
  • Does not invent server package names, registry URLs, image names or MCP tool names that weren't in the user's files; where it recommends an official server it either names one the user already referenced (ghcr.io/github/github-mcp-server) or describes it generically and tells the user to confirm the vendor-published source.
  • Organises the answer by the five stages (gather, correlate, check data, ticket, postmortem draft) and, for each, states what outside data or action the stage needs and which of the user's named systems supplies it.
  • Recommends read-only access for Sentry, Grafana and GitLab: e.g. Sentry token limited to reading events/issues/projects for payments-api (no project write/admin, no resolving issues), a Grafana service account with Viewer role, and a GitLab token with read-only scopes (read_api / read_repository) rather than the full 'api' scope.
  • For the database stage, recommends connecting only to the read replica (never the primary) with a dedicated read-only role, and calls out that the PCI card-data columns (pan_last4, card_token, billing_address) must be excluded, e.g. via a restricted view or column-level grants, rather than trusting the agent to avoid them; may also suggest statement timeouts/row limits.
  • Treats the ticket stage as the only stage that genuinely needs write access, and limits it to creating/updating issues in the PAY team in Linear (no admin, no access to other teams, no deletion), possibly noting a human could approve or the ticket could be created by a person from the agent's draft.
  • States that the postmortem draft stage needs no MCP server, since it writes markdown from what earlier stages already gathered.
  • Gives a no-server fallback per stage that keeps the loop working, e.g. exported Sentry event JSON, Grafana panel CSV/screenshot, a pasted git log or MR diff, psql output pasted by the on-call, and a markdown ticket draft the on-call files by hand.
  • Explicitly lists what each connection must not be able to do (e.g. no deploys, rollbacks or pipeline triggers from GitLab, no alert silencing or dashboard edits in Grafana, no writes or DDL on Postgres, no reading card data), in a form a security reviewer could check.
  • Does not invent MCP server package names, repository URLs or tool names for Sentry, Grafana, GitLab, Linear or Postgres; it either says to use the vendor's officially published server (to be confirmed by the user) or describes the capability generically, and notes that self-hosted Sentry may need verification that the official server supports a custom host.
When it should and shouldn't activate

Should activate:

  • Which MCP servers should we hook up for our release loop? We use GitLab, Linear and Grafana
  • What token scopes does each stage of our build loop need for the GitHub MCP server?
  • Here's our .mcp.json — is this too much access for a weekly status report?
  • We want the on-call agent to read Sentry and Slack. What should we connect and with what permissions?
  • Should our research workflow get a web browsing server and write access to Notion?

Should leave to another skill:

  • Threat-model this agent: it reads support tickets, queries our customer DB and can send email
  • Design an agent loop that keeps our runbooks up to date, with exit criteria and a human gate
  • How should I split this code migration across parallel subagents?
  • Write our company's policy on which AI tools staff may use with client data
  • Walk me through connecting Jira to Claude Code step by step

Hands off to

Related skills

agent-loop-design, ai-usage-policy, subagent-design

Source

SKILL.md · the whole folder on GitHub.