Skip to content

feat: add MCP stdio server exposing standards as tools and resources#2

Merged
lafronzt merged 5 commits into
mainfrom
claude/pensive-greider-f1d2e8
May 24, 2026
Merged

feat: add MCP stdio server exposing standards as tools and resources#2
lafronzt merged 5 commits into
mainfrom
claude/pensive-greider-f1d2e8

Conversation

@lafronzt
Copy link
Copy Markdown
Owner

@lafronzt lafronzt commented May 24, 2026

Summary

  • Adds a Model Context Protocol stdio server (src/mcp/) so AI clients (Claude Desktop, VS Code, etc.) can read engineering standards directly from the same PostgreSQL database as the HTTP API
  • Installs @modelcontextprotocol/sdk and adds mcp:dev / mcp:start npm scripts
  • Documents client configuration and available tools/resources in README.md

What changed

New files

File Purpose
src/mcp/server.ts Entrypoint — wires PrismaClient + StandardsService to the stdio transport; handles graceful shutdown
src/mcp/tools.ts Four read-only tools: list_standards, get_standard, latest_standards, applicable_standards
src/mcp/resources.ts Two resources: standards://latest (static) and standards://rule/{rule_key} (URI template)

Modified files

  • package.json — adds @modelcontextprotocol/sdk dependency and mcp:dev / mcp:start scripts
  • README.md — adds MCP Server section with client config JSON, tool table, and resource table

Design decisions

  • No business logic duplication — all tools call StandardsService and serialize via the existing src/http/serializers.ts
  • Read-only — no write tools; no STANDARDS_API_KEY required for MCP operations
  • Isolated under src/mcp/ — HTTP server and MCP server are independent entrypoints sharing the domain layer
  • changed_paths as array — the MCP tool accepts changed_paths: string[] (natural for JSON), mapped to changedPaths before calling the service (vs. the HTTP API's comma-separated string)

Test plan

  • npm run lint passes
  • npm run build compiles both HTTP and MCP server
  • npm test — all 19 existing tests pass, no regressions
  • Manual: start with npm run mcp:dev and connect an MCP client to verify tool responses

🤖 Generated with Claude Code

Adds a read-only Model Context Protocol server so AI clients can
discover and query engineering standards from the same PostgreSQL
database used by the Fastify HTTP API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 24, 2026 16:34
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a Model Context Protocol (MCP) stdio server entrypoint so MCP-capable AI clients can read engineering standards directly from the same PostgreSQL-backed domain layer used by the existing HTTP API.

Changes:

  • Adds an MCP stdio server under src/mcp/ with read-only tools and JSON resources backed by StandardsService.
  • Adds @modelcontextprotocol/sdk plus mcp:dev / mcp:start npm scripts to run the MCP server.
  • Documents how to run/configure the MCP server and its available tools/resources in README.md.

Reviewed changes

Copilot reviewed 5 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/mcp/tools.ts Registers four read-only MCP tools that call StandardsService and serialize results via existing HTTP serializers.
src/mcp/server.ts MCP stdio server entrypoint wiring Prisma + repository + service and registering tools/resources.
src/mcp/resources.ts Registers two MCP JSON resources (standards://latest and standards://rule/{rule_key}) using StandardsService.
README.md Documents MCP server usage, client configuration, and tool/resource catalog.
package.json Adds MCP scripts and the MCP SDK dependency.
package-lock.json Locks the added MCP SDK dependency and transitive dependencies.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/mcp/tools.ts
Comment thread src/mcp/tools.ts Outdated
Comment thread src/mcp/tools.ts Outdated
Comment thread src/mcp/tools.ts
Comment thread src/mcp/tools.ts Outdated
Comment thread src/mcp/tools.ts
- toolError now serializes AppError code and details into JSON so MCP
  clients get structured error metadata, not just the message string
- get_standard validates rule_key against the same regex as the HTTP API
  to fail fast on malformed keys before touching the database
- list_standards uses z.coerce.number() for limit/offset so LLM-generated
  string values round-trip correctly
- Remove redundant per-type catch branches in get_standard and
  applicable_standards — both paths returned toolError(err) identically
- Add test/mcp-tools.test.ts covering all four tools, changed_paths
  array mapping, empty-result cases, and AppError serialization

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Comment thread src/mcp/tools.ts
Comment thread src/mcp/tools.ts
Comment thread src/mcp/server.ts Outdated
Comment thread test/mcp-tools.test.ts Outdated
- toolError now includes statusCode alongside code and message so MCP
  clients can distinguish error types (400/404/409) without mapping codes
- changed_paths uses .min(1) to reject empty arrays, aligning with the
  HTTP API's "omit instead of empty" contract
- SIGINT/SIGTERM handlers now catch shutdown errors and exit non-zero
  instead of silently swallowing Prisma disconnect failures
- Refactor tool handlers into createHandlers(service) so tests call them
  directly without reaching into SDK private fields; McpServer and
  _registeredTools are no longer referenced in tests

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 4 comments.

Comment thread src/mcp/tools.ts Outdated
Comment thread src/mcp/tools.ts Outdated
Comment thread src/mcp/tools.ts Outdated
Comment thread test/mcp-tools.test.ts Outdated
- Non-AppError exceptions now return a structured JSON internal_error
  payload and log to stderr, preventing internal detail leakage
- listStandards defaults status to "active" in the handler itself so
  the service receives an explicit filter and applies latest-by-ruleKey
  deduplication correctly when called with no arguments
- applicableStandards defaults its argument to {} so invoking the
  handler with no args does not throw on destructuring
- Test updated to call listStandards({}) and assert all returned rules
  are active, actually exercising the default-status contract

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 7 changed files in this pull request and generated 1 comment.

Comment thread src/mcp/tools.ts
Keeps the error shape consistent — all toolError payloads now include
code, message, and statusCode regardless of the error type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@lafronzt lafronzt merged commit f81fec1 into main May 24, 2026
1 check failed
@lafronzt lafronzt deleted the claude/pensive-greider-f1d2e8 branch May 24, 2026 17:33
lafronzt added a commit that referenced this pull request May 24, 2026
- package.json / README.md: keep mcp:http:dev and mcp:http:start scripts
  and Streamable HTTP section added in this branch
- src/mcp/tools.ts: take main's version which includes statusCode: 500
  in the internal_error fallback (added in PR #2)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants