feat: add MCP stdio server exposing standards as tools and resources#2
Merged
Conversation
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>
There was a problem hiding this comment.
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 byStandardsService. - Adds
@modelcontextprotocol/sdkplusmcp:dev/mcp:startnpm 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.
- 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>
- 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>
- 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>
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
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
src/mcp/) so AI clients (Claude Desktop, VS Code, etc.) can read engineering standards directly from the same PostgreSQL database as the HTTP API@modelcontextprotocol/sdkand addsmcp:dev/mcp:startnpm scriptsREADME.mdWhat changed
New files
src/mcp/server.tsPrismaClient+StandardsServiceto the stdio transport; handles graceful shutdownsrc/mcp/tools.tslist_standards,get_standard,latest_standards,applicable_standardssrc/mcp/resources.tsstandards://latest(static) andstandards://rule/{rule_key}(URI template)Modified files
package.json— adds@modelcontextprotocol/sdkdependency andmcp:dev/mcp:startscriptsREADME.md— adds MCP Server section with client config JSON, tool table, and resource tableDesign decisions
StandardsServiceand serialize via the existingsrc/http/serializers.tsSTANDARDS_API_KEYrequired for MCP operationssrc/mcp/— HTTP server and MCP server are independent entrypoints sharing the domain layerchanged_pathsas array — the MCP tool acceptschanged_paths: string[](natural for JSON), mapped tochangedPathsbefore calling the service (vs. the HTTP API's comma-separated string)Test plan
npm run lintpassesnpm run buildcompiles both HTTP and MCP servernpm test— all 19 existing tests pass, no regressionsnpm run mcp:devand connect an MCP client to verify tool responses🤖 Generated with Claude Code