Skip to content

feat(mcp-server): curated tool registry & input validation (MCP Prompt 10)#4011

Merged
gilgardosh merged 2 commits into
mcp-setupfrom
claude/mcp-prompt-10-tool-registry
Jul 26, 2026
Merged

feat(mcp-server): curated tool registry & input validation (MCP Prompt 10)#4011
gilgardosh merged 2 commits into
mcp-setupfrom
claude/mcp-prompt-10-tool-registry

Conversation

@gilgardosh

Copy link
Copy Markdown
Collaborator

Summary

Implements Prompt 10 – Tool registry contracts and input validation (see
docs/mcp/spec.md §8.3). Adds the curated tool
registry abstraction that later production tools plug into.

Stacked PR: targets claude/mcp-prompt-09-identity-mapping (Prompt 09, #4010).
Review/merge Prompts 05→09 first; this diff shows only the Prompt 10 changes.

Changes

  • src/tools/registry.ts
    • ToolDefinition<Schema>name, description, a strict zod inputSchema, a ToolAuthPolicy, and a pure handler(input, context).
    • ToolAuthPolicy (requiredRoles, requiresBusinessScope, dataClassification) and ToolExecutionContext (auth, readScope, correlationId) — contracts the policy evaluator (Prompt 11) and handlers (Prompt 13+) consume.
    • ToolRegistryregister / has / get / list (registration order preserved) with DuplicateToolError on name collisions; describe() renders each input schema to JSON Schema (additionalProperties: false) for tools/list.
    • validateToolInput() — strict parse (unknown fields rejected) returning either the typed data or a deterministic VALIDATION_ERROR payload (code, message, field-path issues).
  • Tests — registration, duplicate rejection, ordering, describe() JSON Schema, and validation (valid, missing-required, unknown-field, type-mismatch). 120 tests total.

Validation

  • yarn workspace @accounter/mcp-server test → 120 passed
  • yarn workspace @accounter/mcp-server lint / typecheck / build → pass

Notes

  • Registry and validation are not yet wired into POST /mcp — the smoke tool still answers tools/list/tools/call directly. The registry becomes the source of truth once the first real tool + the policy evaluator land (Prompts 11/13); the smoke stub is removed at final wiring (Prompt 24).
  • dataClassification / requiredRoles are defined here but enforced in Prompt 11.

🤖 Generated with Claude Code


Generated by Claude Code

@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:18 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:18 — with GitHub Actions Inactive

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a curated tool registry (ToolRegistry) and validation layer (validateToolInput) using Zod schemas for strict input validation, along with corresponding unit tests. The feedback suggests replacing the non-standard z.toJSONSchema method with the explicitly imported zodToJsonSchema function from zod-to-json-schema to ensure runtime compatibility and type safety.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/mcp-server/src/tools/registry.ts Outdated
Comment thread packages/mcp-server/src/tools/registry.ts
@gilgardosh
gilgardosh force-pushed the claude/mcp-prompt-09-identity-mapping branch from 743418f to 9080929 Compare July 21, 2026 16:12
@gilgardosh
gilgardosh force-pushed the claude/mcp-prompt-10-tool-registry branch from cc1631c to 94a27f0 Compare July 21, 2026 16:12
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 16:13 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 16:13 — with GitHub Actions Inactive
@gilgardosh gilgardosh self-assigned this Jul 22, 2026
@gilgardosh
gilgardosh force-pushed the claude/mcp-prompt-09-identity-mapping branch from 9080929 to c280fe9 Compare July 26, 2026 08:48
@gilgardosh
gilgardosh requested a review from Copilot July 26, 2026 15:20

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Adds the curated tool registry contracts and strict input validation layer for the new @accounter/mcp-server package, along with supporting MCP server scaffolding (HTTP transport skeleton, OAuth discovery helpers, auth primitives) and a comprehensive unit-test suite to keep behavior deterministic and hermetic.

Changes:

  • Introduces ToolRegistry + ToolDefinition contracts and validateToolInput() with strict unknown-field rejection and deterministic validation error payloads.
  • Adds MCP server foundations (request context/logging, OAuth protected-resource metadata + 401 challenge helper, JSON-RPC parsing/dispatch, Auth0 token verification + identity mapping).
  • Updates docs/spec + implementation blueprint and wires workspace-local TS/Vitest config for isolated testing.

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
yarn.lock Adds the new workspace package’s dependency set to the lockfile.
packages/mcp-server/vitest.config.ts Package-scoped Vitest config for isolated test runs.
packages/mcp-server/tsconfig.json Package TS build config (ESM, strict, dist output).
packages/mcp-server/src/version.ts Runtime service name/version helpers for health/logging.
packages/mcp-server/src/tools/registry.ts Tool registry contracts, JSON-Schema description, strict input validation.
packages/mcp-server/src/tools/tests/registry.test.ts Unit tests for registry behavior and validation payloads.
packages/mcp-server/src/server.ts Minimal node:http server with routing, health, and shutdown.
packages/mcp-server/src/oauth/metadata.ts RFC 9728 protected-resource metadata document builder + URL helper.
packages/mcp-server/src/oauth/challenge.ts Standard 401 WWW-Authenticate Bearer challenge builder/sender.
packages/mcp-server/src/oauth/tests/metadata.test.ts Contract tests for protected-resource metadata shape and URL joining.
packages/mcp-server/src/oauth/tests/challenge.test.ts Contract tests for 401 challenge header escaping/body behavior.
packages/mcp-server/src/mcp/tools.ts Placeholder “smoke tool” surface for the early MCP skeleton.
packages/mcp-server/src/mcp/jsonrpc.ts Minimal JSON-RPC request/response primitives + request-shape validation.
packages/mcp-server/src/mcp/handler.ts MCP HTTP handler (auth boundary + body read + JSON-RPC dispatch).
packages/mcp-server/src/mcp/tests/jsonrpc.test.ts Tests for JSON-RPC helpers and request-shape narrowing.
packages/mcp-server/src/mcp/tests/handler.test.ts End-to-end-ish tests for MCP handler dispatch, auth, and size limits.
packages/mcp-server/src/logger.ts Minimal structured JSON logger + request-bound logger helpers.
packages/mcp-server/src/index.ts Entrypoint wiring: start server + process-level error handlers.
packages/mcp-server/src/context.ts Per-request requestId/correlationId creation and storage.
packages/mcp-server/src/config/env.ts Strict env parsing/normalization with fail-fast error reporting.
packages/mcp-server/src/config/tests/env.test.ts Tests for env parsing defaults and invalid configurations.
packages/mcp-server/src/auth/verifier.ts Auth0 JWKS-backed access-token verifier (cached by JWKS URL).
packages/mcp-server/src/auth/token.ts Bearer extraction, jose verification wrapper, and principal shape.
packages/mcp-server/src/auth/identity.ts Identity→memberships mapping + read-scope narrowing helpers.
packages/mcp-server/src/auth/tests/token.test.ts Tests for token extraction and verification error classification.
packages/mcp-server/src/auth/tests/identity.test.ts Tests for membership parsing, dedupe, and scope narrowing semantics.
packages/mcp-server/src/tests/server.test.ts Server routing/shutdown/health tests (log silencing included).
packages/mcp-server/src/tests/logger.test.ts Tests for logger output safety and context field merging.
packages/mcp-server/src/tests/index.test.ts Ensures entrypoint exports are wired.
packages/mcp-server/src/tests/context.test.ts Tests for correlation id inheritance and route parsing behavior.
packages/mcp-server/README.md Package documentation for local running, OAuth discovery, and config.
packages/mcp-server/package.json Declares the new workspace package, scripts, and dependencies.
docs/mcp/spec.md Updates/introduces spec content referenced by the prompt pack.
docs/mcp/implementation-blueprint.md Updates the step-by-step prompt pack/blueprint for incremental delivery.
Comments suppressed due to low confidence (1)

packages/mcp-server/src/config/env.ts:64

  • Same issue for AUTH0_JWKS_URL: { error: ... } likely doesn’t set a message in Zod. This makes validation errors less informative than intended.
  AUTH0_JWKS_URL: emptyStringAsUndefined(
    zod.url({ error: 'AUTH0_JWKS_URL must be a valid URL' }).optional(),
  ),

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

Comment thread packages/mcp-server/src/config/env.ts
Comment thread packages/mcp-server/src/server.ts Outdated
Comment thread packages/mcp-server/src/mcp/handler.ts Outdated
Comment thread packages/mcp-server/src/tools/registry.ts
@gilgardosh
gilgardosh force-pushed the claude/mcp-prompt-10-tool-registry branch from 94a27f0 to e2773cd Compare July 26, 2026 16:05
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 26, 2026 16:05 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 26, 2026 16:05 — with GitHub Actions Inactive
Base automatically changed from claude/mcp-prompt-09-identity-mapping to mcp-setup July 26, 2026 16:23
claude added 2 commits July 26, 2026 19:27
Add the production-ready tool registry abstraction (docs/mcp/spec.md §8.3).

- src/tools/registry.ts: ToolDefinition (name, description, strict zod input
  schema, auth policy, pure handler); ToolRegistry with register/get/has/list
  and duplicate-name rejection; describe() renders input schemas to JSON Schema
  (additionalProperties:false) for tools/list
- validateToolInput(): strict parsing with unknown-field rejection and a
  deterministic VALIDATION_ERROR payload (code, message, field-path issues)
- ToolAuthPolicy / DataClassification / ToolExecutionContext contracts for the
  policy evaluator and handlers in later steps
- unit tests for registration, duplicates, ordering, describe(), and schema
  validation (valid, missing required, unknown field, type mismatch)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPMszz9gdZFhNjobRm6Ndo
…hema strictness

Address PR review feedback on Prompt 10:

- MCP_ENABLED=0 now actually disables the connector: the MCP transport (`/mcp`)
  and its OAuth protected-resource-metadata discovery route return 404 (health
  only), instead of being served while the logs claim "disabled mode".
- `tools/call` returns a clear InvalidParams ("params must be an object") when
  `params` is an array or other non-object, instead of a misleading
  "Unknown tool: undefined".
- `registry.describe()` renders JSON Schema from the same `.strict()` schema that
  `validateToolInput` enforces, so the advertised `additionalProperties: false`
  provably matches the runtime unknown-field rejection.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPMszz9gdZFhNjobRm6Ndo
@gilgardosh
gilgardosh force-pushed the claude/mcp-prompt-10-tool-registry branch from e2773cd to 49992ce Compare July 26, 2026 16:27
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 26, 2026 16:28 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 26, 2026 16:28 — with GitHub Actions Inactive
@gilgardosh
gilgardosh merged commit 02d549c into mcp-setup Jul 26, 2026
8 checks passed
@gilgardosh
gilgardosh deleted the claude/mcp-prompt-10-tool-registry branch July 26, 2026 16:36
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.

3 participants