Skip to main content
Glama

mcp-devops-agent

A Model Context Protocol server that gives an AI assistant a small, typed set of GitHub tools, and a command-line agent that calls those tools in a loop.

This is a portfolio project by Humberto Vieira, a senior React and TypeScript developer moving into AI engineering. The interesting part is not a chat wrapper. It is the boundary between a model and a side effect: schema-validated tools, a protocol a host can launch, a step budget, and a confirmation gate in front of writes. The same server runs inside Claude Desktop, Cursor, or the CLI agent. The agent never imports the GitHub client. It only speaks MCP.

Nothing here is deployed, and the repository does not claim usage numbers. Tests and evals run against an in-memory GitHub and a scripted model, so they do not need API keys.

What it does

Ask a host, or the CLI, things like:

  • Give me a morning standup summary of my repos.

  • Which open pull requests have a failing check?

  • Summarize pull request 17 in acme/web.

  • Open an issue on acme/web titled "Investigate checkout CI".

Reads run immediately. Creating an issue is a write: the CLI asks before it calls GitHub, and it refuses the write in a non-interactive shell unless you pass --yes. Claude Desktop and Cursor have their own approval UI. The server marks create_issue with readOnlyHint: false so a host can tell the difference.

Related MCP server: GitHub MCP Server

Architecture

flowchart LR
  subgraph hosts [Hosts]
    Claude[Claude Desktop]
    Cursor[Cursor]
  end

  subgraph cli [devops-agent]
    Model[Anthropic or OpenAI adapter]
    Loop[Tool-calling loop]
    Guard[Step budget and write confirmation]
  end

  subgraph mcp [devops-mcp]
    Protocol[MCP server]
    Tools[Tools, resources, prompts]
    GitHubClient[GitHub REST client]
  end

  API[(GitHub REST API)]

  Claude -->|stdio| Protocol
  Cursor -->|stdio or local HTTP| Protocol
  Model --> Loop --> Guard
  Guard -->|MCP client over stdio| Protocol
  Protocol --> Tools --> GitHubClient --> API

The CLI reads devops://watchlist before the first model turn and puts those repositories in the system prompt. Hosts that already surface MCP resources can read the same URI themselves. Prompts are templates the host fills in. They are not tools, and the model does not have to call them.

summarize_pull_request does not call a language model. It returns a bounded digest of the pull request and the diff. The host model writes the prose. That keeps the tool deterministic, testable, and free of a second hidden prompt.

Tools, resources, and prompts

Name

Kind

Effect

list_open_pull_requests

Tool, read

Open pull requests plus a CI rollup. Failure wins over pending, which wins over success. No checks at all is unknown, not a pass.

summarize_pull_request

Tool, read

Title, author, branches, truncated description, and truncated patches.

list_issues

Tool, read

Issues only. GitHub's issues API also returns pull requests; those are filtered out of the first page.

get_repo_activity

Tool, read

Commits, updated issues, and updated pull requests. Defaults to the last 24 hours.

create_issue

Tool, write

Opens an issue. Not idempotent: calling it twice creates two issues.

devops://watchlist

Resource

JSON list of owner / repo pairs from GITHUB_REPOS.

github://repo/{owner}/{repo}

Resource template

Description, default branch, visibility, and open-issue count. Watched repos are also listed.

morning_standup

Prompt

Tells the model to read the watchlist, then activity and open pull requests, and to write a standup from those results only.

pr_review_brief

Prompt

Tells the model to brief one pull request from summarize_pull_request.

Every tool argument is a Zod schema. The MCP SDK turns that schema into the JSON Schema the model sees and rejects a bad call before the handler runs. GitHub responses are parsed with Zod as well, so a shape the client does not understand becomes an error instead of a silent undefined. Tool failures are returned as isError: true with a message the model can read. The token is never accepted as an argument, and it is stripped from error text if an upstream body echoes it.

Lists are the first page only, with a cap of 30. Diff text defaults to 8,000 characters and cannot exceed 20,000. That is a context-window limit, not a claim that the digest is a full review.

Requirements

  • Node.js 20 or newer. CI uses Node 22.

  • A GitHub personal access token only when you call the real API. Classic tokens need repo for private repositories. Fine-grained tokens need read access to metadata, pull requests, issues, and commit statuses. Check-run details also need permission to read checks. If that permission is missing, the pull-request tool keeps the combined commit status and says so.

  • ANTHROPIC_API_KEY or OPENAI_API_KEY only for the CLI agent. Claude Desktop and Cursor use their own model.

This project does not load a .env file. .env.example is a checklist. Export the variables in your shell, or put them in the host's MCP config. The host config is the better place for the token, because the server process receives it and the chat does not.

Setup from a fresh clone

git clone https://github.com/hjsvieira98/mcp-devops-agent.git
cd mcp-devops-agent
npm install
npm test
npm run eval
npm run lint
npm run build

npm test and npm run eval do not call GitHub or a model provider.

Run the server over stdio. It waits for a host. Logs go to stderr, because stdout is the JSON-RPC stream.

export GITHUB_TOKEN="github_pat_..."
export GITHUB_REPOS="owner/repo,owner/other"
node dist/index.js

During development you can skip the build:

npm run dev

Optional local HTTP, bound to 127.0.0.1 only. The SDK's localhost Host and Origin checks sit in front of the handler. GET /health is a plain liveness check. The MCP endpoint is POST /mcp.

npm run dev:http
# devops-mcp listening on http://127.0.0.1:3333/mcp

MCP_HTTP_PORT changes the port. Prefer stdio for a desktop host. Use HTTP when a client attaches to a URL you already started. Do not expose this process beyond your machine: it holds your GitHub token and it does not authenticate callers.

The MCP Inspector can list and call the tools without a chat host:

npx @modelcontextprotocol/inspector node dist/index.js

Set GITHUB_TOKEN and GITHUB_REPOS in that shell first.

Claude Desktop

Claude Desktop launches the server as a child process. Merge this into the config file:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

  • Windows: %APPDATA%\Claude\claude_desktop_config.json

Use the absolute path to dist/index.js from the clone. Restart Claude Desktop after saving.

{
  "mcpServers": {
    "devops-mcp": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/mcp-devops-agent/dist/index.js"],
      "env": {
        "GITHUB_TOKEN": "github_pat_...",
        "GITHUB_REPOS": "owner/repo,owner/other"
      }
    }
  }
}

In the chat, you can ask for a standup or attach the morning_standup prompt if the client lists prompts. The server instructions tell the model that create_issue writes to GitHub and that it should not ask you to paste a token.

Cursor

Project config (.cursor/mcp.json) or user config (~/.cursor/mcp.json):

{
  "mcpServers": {
    "devops-mcp": {
      "command": "node",
      "args": ["/ABSOLUTE/PATH/mcp-devops-agent/dist/index.js"],
      "env": {
        "GITHUB_TOKEN": "github_pat_...",
        "GITHUB_REPOS": "owner/repo,owner/other"
      }
    }
  }
}

If the server is already running with --http, Cursor can attach by URL instead of launching a process:

{
  "mcpServers": {
    "devops-mcp": {
      "url": "http://127.0.0.1:3333/mcp"
    }
  }
}

The token still lives in the server process, not in Cursor's chat.

CLI agent

The agent is a separate program. It spawns the MCP server, lists tools, and runs a loop: ask the model, call the tools it requested, append the results, repeat. When the model stops requesting tools, that text is the answer.

export GITHUB_TOKEN="github_pat_..."
export GITHUB_REPOS="owner/repo,owner/other"
export ANTHROPIC_API_KEY="sk-ant-..."
# optional: LLM_PROVIDER=openai and OPENAI_API_KEY instead
# optional: LLM_MODEL=claude-sonnet-5-5 or gpt-5.4
npm run agent -- "Give me a morning standup summary of my repos"

LLM_PROVIDER is optional when only one key is set. The default models are claude-sonnet-5-5 and gpt-5.4. Override them with LLM_MODEL when you want a different snapshot. The adapters talk to the providers over HTTP. They do not depend on the provider SDKs, and they do not send sampling parameters such as temperature.

Model keys are not copied into the server's environment. The child receives PATH and the GitHub variables only.

npm run agent -- --max-steps 4 "Which pull requests are failing CI?"
npm run agent -- --yes "Open an issue on owner/repo titled \"Investigate flaky login\""

--max-steps is the number of tool executions allowed, from 1 to 30, default 8. A declined write counts, so a model cannot spend the budget retrying a confirmation you refused. After the budget is spent, the model gets one more turn with the tools removed and has to answer from what it already collected.

Without --yes, a terminal prompts on stderr:

About to call create_issue with {
  "owner": "owner",
  "repo": "repo",
  "title": "Investigate flaky login"
}
Proceed? [y/N]

A pipe or CI job is not a terminal. The write is denied unless --yes is present. Progress is printed to stderr. The final answer is printed to stdout.

After npm run build, the same CLI is node dist/agent/cli.js. npm run agent uses tsx and spawns src/index.ts, so the build is optional for local runs and required for the host config above.

Example session

This transcript uses the fixture repositories from the eval suite (acme/web and acme/api). It shows the CLI's real progress format. The standup paragraph is an illustration of the answer the system prompt asks for, written from those fixture facts. It is not a recording of a live model, and it is not a log from a real GitHub account.

$ npm run agent -- "Give me a morning standup summary of my repos."
devops-agent  provider=anthropic model=claude-sonnet-5-5  maxSteps=8
watched: acme/web, acme/api
→ get_repo_activity {"owner":"acme","repo":"web"}
← get_repo_activity ok
→ list_open_pull_requests {"owner":"acme","repo":"web"}
← list_open_pull_requests ok
→ get_repo_activity {"owner":"acme","repo":"api"}
← get_repo_activity ok
→ list_open_pull_requests {"owner":"acme","repo":"api"}
← list_open_pull_requests ok

Since yesterday on acme/web, ada committed "Add health check".
Pull request #17, "Reduce checkout latency", is open and its CI rollup is failure
(the build status and the unit check both failed).
acme/api has no commits in the window. Pull request #8, "Document auth", is open
and its build status is success.
Next: look at the failing build on #17 before reviewing the checkout change.

A matching eval, morning-standup, drives the real server and the real loop with a scripted model. It asserts those four tool calls, asserts create_issue was not executed, and asserts the final text contains facts that were present only in the tool results (Reduce checkout latency, failure, Document auth, Add health check). That checks the wiring. It does not score a live model.

Tests and evals

npm test          # Vitest. GitHub fetch and both model APIs are mocked.
npm run eval      # Prints PASS/FAIL for each agent scenario.
npm run typecheck
npm run lint
npm run format:check

GitHub Actions runs lint, format, typecheck, tests, evals, and the production build on pull requests.

The eval scenarios live in src/evals/scenarios.ts:

Scenario

What it locks in

morning-standup

Activity and open pull requests for each watched repo, and no writes.

pr-digest

summarize_pull_request for a named pull request, and the filename comes back from the tool.

create-issue-declined

Confirmation denied. The GitHub client never sees createIssue.

create-issue-confirmed

Confirmation allowed. The created issue number is #101 from the fixture.

step-budget

maxSteps: 2 stops a model that would keep calling list_issues.

The scripted model is a replay, not a judge. Its final sentence is built from the tool text it was given, so a broken loop that drops tool results fails the scenario. Replacing that replay with a live model, or adding a model-graded rubric, is future work and would need keys.

Design decisions

One server, three hosts. Tools are registered in createDevOpsServer. Stdio (serveStdio) and Streamable HTTP (createMcpHandler) are thin entries around that factory. The official MCP TypeScript SDK v2 (@modelcontextprotocol/server and @modelcontextprotocol/client) implements the 2026-07-28 revision and, by default, still serves 2025-era clients. Desktop hosts that spawn a local process speak stdio, so that is the path the config samples use.

The agent is an MCP client. It cannot call GitHubRestClient directly. A change to a tool is visible to Claude Desktop, Cursor, and the CLI together. The cost is an extra process and a JSON-RPC hop, which is the point of the protocol.

Validation on the way in and on the way out. Zod schemas on tool inputs stop a bad owner before any HTTP call. Zod schemas on GitHub JSON stop a partial payload from becoming a pull request with a missing SHA. The handler then returns structuredContent that the SDK checks against the tool's outputSchema.

CI is two GitHub APIs. Commit statuses and check runs are different systems. The rollup merges them and prefers failure over pending over success. A cancelled, timed-out, or action-required check counts as failure. A skipped or neutral check does not. If the token cannot read check runs, the tool reports the denial and still returns statuses, instead of failing the whole call.

Writes are gated in the client, not by blocking on stdin inside the server. The server's stdin is the protocol stream. A confirmation prompt there would corrupt JSON-RPC. The CLI asks the user. Hosts do the equivalent with their own permission UI, using readOnlyHint. A tool with no hint is treated as a write. The safe default is to ask.

Bounded pages and patches. The first page is a product decision. Following every Link header would make a standup call unbounded on a busy repository. The digest says when a patch or a file list was cut short, and the prompts tell the model to pass that on.

Credentials stay in the process that needs them. GITHUB_TOKEN is read by the server. The agent drops ANTHROPIC_API_KEY and OPENAI_API_KEY from the child environment. Tool arguments have no token field, so the model is not asked to repeat one.

Evals that can fail in CI. A scenario file that nobody runs does not constrain the loop. npm run eval executes the scenarios in-process over InMemoryTransport, with MemoryGitHub behind the same tool handlers the stdio server uses.

Project layout

src/index.ts            stdio by default, --http for Streamable HTTP
src/server/             tool, resource, and prompt registration
src/github/             REST client, errors, and the in-memory client used by tests
src/agent/              loop, guardrails, provider adapters, CLI
src/evals/              scenarios and the runner behind npm run eval
tests/                  Vitest

Roadmap

These are not started. They are the next pieces this design leaves room for.

  • GitHub App installation tokens instead of a personal access token, with the installation id in the server environment.

  • A cursor argument so a caller can request the next page of pull requests or issues, still with a hard cap.

  • Reviewers, review state, and a bounded slice of workflow logs for a failed check.

  • MCP OAuth on the HTTP entry, so a shared server does not rely on a token in the environment. The local stdio path would stay as it is.

  • Live-model evals with a frozen fixture set, kept separate from the deterministic tool-call checks above.

License

MIT © 2026 Humberto Vieira

Available Tools

5 tools
create_issueCreate an issueA

Open a GitHub issue in one repository. This writes to GitHub. Call it only when the user has explicitly asked to create an issue. Creating the same issue twice creates two issues.

NameRequiredDescriptionDefault
bodyNoIssue body in Markdown
repoYesRepository name, without the owner
ownerYesGitHub user or organization login
titleYesIssue title
labelsNoLabel names that already exist on the repository

Output Schema

NameRequiredDescription
urlYes
repoYes
ownerYes
stateYes
titleYes
authorYes
labelsYes
numberYes
updatedAtYes
bodyExcerptYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, openWorldHint=true and idempotentHint=false; the description reinforces the write side effect ("This writes to GitHub") and, more usefully, explains the consequence of non-idempotency in concrete terms — duplicate calls create duplicate issues. It stops short of permission/scope requirements or rate-limit behavior, which the annotations do not cover.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with purpose then side effect then precondition then pitfall. No filler, and each sentence carries a distinct decision-relevant fact.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full schema coverage, the description needn't explain return values or parameters, and it covers the two things an agent could get wrong: calling unprompted and creating duplicates. Missing only auth/permission context for a mutating open-world tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%; every parameter including labels and body format is documented in the schema. The description adds only the "one repository" framing, which duplicates the owner/repo semantics rather than extending them. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Open a GitHub issue in one repository" is a specific verb+resource with explicit scope, unambiguous against the read-only siblings (list_issues, get_repo_activity). It does not name a sibling for contrast, so the differentiation is inferable rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

"Call it only when the user has explicitly asked to create an issue" gives a clear, checkable precondition and implicitly excludes autonomous use. No alternative tool or fallback path is named for the case where the user only wants to read or search issues.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_repo_activityGet repository activityA
Read-onlyIdempotent

Recent commits, updated issues, and updated pull requests since a timestamp. Defaults to the last 24 hours. Returns the first page of each list only.

NameRequiredDescriptionDefault
repoYesRepository name, without the owner
limitNoMaximum number of items to return. Defaults to 10. The tool returns the first page only.
ownerYesGitHub user or organization login
sinceNoISO-8601 start of the window. Defaults to 24 hours before the server clock.

Output Schema

NameRequiredDescription
repoYes
ownerYes
sinceYes
untilYes
commitsYes
issuesUpdatedYes
pullRequestsUpdatedYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

It provides key behavioral constraints not present in annotations or basic schemas, specifically that it defaults to 24 hours and returns only the first page of results. This is crucial operational information for the agent.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief, direct, and efficient, immediately stating what the tool does and ending with two essential constraints regarding defaults and output scope.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given that the parameter schema is complete and the tool is read-only/idempotent, the description provides all necessary behavioral context and operational limits (defaults/paging) required for correct and safe invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

While the schema has 100% coverage, the description clarifies that the 'since' parameter relates to a temporal window starting point and explicitly states the pagination constraint (returns first page only), adding semantic value beyond the structured data.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies the exact resources returned: commits, issues, and pull requests. It clearly distinguishes this aggregate functionality from specific list tools like list_issues or list_open_pull_requests.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description sets clear expectations by mentioning the default time window (last 24 hours) and limits the scope to the first page of results, helping the agent understand its operational context and limitations.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_issuesList issuesA
Read-onlyIdempotent

List issues for one repository. Pull requests are omitted because GitHub returns them from the issues API. Returns the first page only, so a page that is mostly pull requests can yield fewer issues than the limit.

NameRequiredDescriptionDefault
repoYesRepository name, without the owner
limitNoMaximum number of items to return. Defaults to 10. The tool returns the first page only.
ownerYesGitHub user or organization login
stateNoIssue state. Defaults to open.

Output Schema

NameRequiredDescription
repoYes
ownerYes
stateYes
issuesYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly/openWorld/idempotent, and the description adds genuinely useful behavior beyond them: PRs are silently excluded and truncation means the returned count can fall short of `limit`. It stops short of covering auth requirements or rate limits, but the caveats it does give are the ones an agent would otherwise trip on.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, front-loaded with the core purpose and followed by the two behavioral caveats that matter. Nothing repetitive or wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return values need no explanation, and annotations cover the safety profile. The remaining substance an agent needs — scope, PR omission, first-page truncation — is all present, leaving only minor gaps like sorting and auth.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the baseline is 3, but the description adds real meaning to `limit` by explaining that the first-page-only behavior can make the effective result count lower than the requested limit — something the schema does not convey.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List issues") plus an explicit scope ("for one repository"). The note that pull requests are omitted effectively separates it from the sibling list_open_pull_requests and summarize_pull_request tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied rather than stated: the agent learns this returns only the first page and may return fewer than `limit`, but there is no explicit when-to-use guidance, no mention of how to get more results, and no routing guidance relative to get_repo_activity or the PR siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_open_pull_requestsList open pull requestsA
Read-onlyIdempotent

List open pull requests for one repository and roll up CI. Failure wins over pending, which wins over success. An empty check set is "unknown", not passing. Returns the first page only.

NameRequiredDescriptionDefault
repoYesRepository name, without the owner
limitNoMaximum number of items to return. Defaults to 10. The tool returns the first page only.
ownerYesGitHub user or organization login

Output Schema

NameRequiredDescription
repoYes
ownerYes
warningsYes
pullRequestsYes

TDQS

A3.9/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and idempotentHint, so safety is covered. The description adds genuinely non-obvious behavior: the precedence rule (failure > pending > success), the empty-check-set = "unknown" edge case, and the pagination limitation. Only the return shape per PR is left unstated, which the output schema covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four short sentences, front-loaded with the action before the aggregation rules. The final sentence mildly duplicates the limit parameter's schema note, keeping it just short of full marks.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present, return structure need not be explained, and the description covers the ambiguous parts of the output (CI rollup precedence, unknown state) plus the pagination boundary. A note on sort order or what happens beyond the first page would make it complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so owner, repo, and limit are already documented at the field level. The description adds only the repository-scoping framing and repeats the first-page constraint already present in the limit description; baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ("List open pull requests") plus the scope constraint ("for one repository") and an additional computed dimension (CI rollup). An agent can distinguish this from list_issues or summarize_pull_request without inspecting schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage context is implied by "for one repository" and "first page only," which tell the agent this is a single-repo, non-paginating listing. However, it never names an alternative or states when not to use it — e.g., that summarize_pull_request is the right tool for a single PR's detail.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

summarize_pull_requestSummarize a pull request diffA
Read-onlyIdempotent

Fetch one pull request and return a bounded digest of its metadata, description, and diff. Patches are truncated. This tool does not call a language model; the host writes the prose from the digest.

NameRequiredDescriptionDefault
repoYesRepository name, without the owner
ownerYesGitHub user or organization login
numberYesPull request number
fileLimitNoMaximum files to include. Defaults to 20.
maxPatchCharsNoTotal characters of patch text to keep across all files. Defaults to 8000.

Output Schema

NameRequiredDescription
urlYes
bodyYes
repoYes
draftYes
filesYes
ownerYes
titleYes
authorYes
numberYes
baseRefYes
headRefYes
headShaYes
additionsYes
deletionsYes
bodyTruncatedYes
filesTruncatedYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds real context beyond the annotations: patches are truncated, the digest is bounded, and critically the host (not the tool) writes the prose — an agent that expected a finished summary would otherwise be misled. Nothing is said about auth requirements or rate limits, so not a 5.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three short sentences, zero filler, with the core behavior (what is returned) front-loaded and the important caveat about no LLM call placed where it will actually be read.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists and parameter coverage is complete, so return values needn't be spelled out. The description covers truncation, digest bounding, and the no-LLM contract — sufficient for correct invocation, though it could note the default limits inline.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% and every parameter, including fileLimit and maxPatchChars with their defaults and bounds, is documented in-schema. The description's mention of a 'bounded digest' and truncated patches reinforces those limits but adds no syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Fetch one pull request') plus precisely what it returns ('a bounded digest of its metadata, description, and diff'). The singular 'one pull request' implicitly distinguishes it from the list_open_pull_requests sibling, but no sibling is named explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use or when-not guidance, and no alternatives are named among list_open_pull_requests, get_repo_activity, or the issue tools. The note about not calling a language model sets expectations about output but does not route the agent's tool choice.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 5 tool updatesv0.1.0
    • First observedcreate_issue
    • First observedget_repo_activity
    • First observedlist_issues
    • First observedlist_open_pull_requests
    • First observedsummarize_pull_request

TDQS

A3.9/5.0

Scored across 5 tools

Disambiguation4/5

Each tool maps to a distinct resource+action: listing open PRs with CI rollup, digesting one PR, listing issues, creating an issue, and a cross-resource activity feed. The only mild overlap is between list_open_pull_requests and get_repo_activity (which also surfaces updated PRs), but the descriptions make the boundary clear (CI-focused open list vs. time-windowed feed).

Naming Consistency5/5

All five names follow a strict snake_case verb_noun pattern: list_open_pull_requests, summarize_pull_request, list_issues, create_issue, get_repo_activity. Verbs (list/summarize/create/get) are used consistently with their implied semantics.

Tool Count4/5

Five focused tools sit comfortably in the reasonable range and each earns its place around the PR/issue workflow. It is slightly lean for a server branded "devops," which implies CI/CD and deployment operations beyond pull requests and issues.

Completeness3/5

Read paths are solid (PR list+digest, issue list, activity feed) but the write surface is a single create_issue. There is no create/merge/comment on pull requests and no update/close/comment on issues, so common follow-up actions become dead ends for an agent.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers