Skip to content

MCP setup#3941

Open
gilgardosh wants to merge 15 commits into
mainfrom
mcp-setup
Open

MCP setup#3941
gilgardosh wants to merge 15 commits into
mainfrom
mcp-setup

Conversation

@gilgardosh

Copy link
Copy Markdown
Collaborator

No description provided.

@gilgardosh gilgardosh self-assigned this Jul 15, 2026
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 15, 2026 15:37 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 15, 2026 15:37 — 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 the specification and implementation blueprint for the Accounter MCP Connector, establishing a clear, multi-phase plan to expose read-only capabilities to Claude clients. The review feedback highlights key areas for improvement, including propagating the user's bearer token to the upstream GraphQL client, reusing existing shared auth utilities for token verification, enforcing strict size and TTL limits on the in-process cache to prevent memory exhaustion, and aligning Auth0 environment variables with the existing server configuration.

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 docs/mcp/implementation-blueprint.md Outdated
Comment thread docs/mcp/implementation-blueprint.md Outdated
Comment thread docs/mcp/spec.md Outdated
Comment thread docs/mcp/spec.md Outdated
@github-actions

github-actions Bot commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

🚀 Snapshot Release (alpha)

The latest changes of this PR are available as alpha on npm (based on the declared changesets):

Package Version Info
@accounter/client 0.1.0-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/gmail-listener 0.1.3-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/israeli-vat-scraper 0.1.13-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/modern-poalim-scraper 0.10.7-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/scraper-app 0.0.3-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/server 0.2.0-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/shaam-uniform-format-generator 0.2.7-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎
@accounter/shaam6111-generator 0.1.9-alpha-20260721160522-ec45a522bd0bb0917e824f9ba3d53c1ccf32da04 npm ↗︎ unpkg ↗︎

@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 16, 2026 12:32 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 16, 2026 12:32 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 11:35 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 11:35 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:01 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:01 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:03 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:03 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:10 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:11 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:43 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:43 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:55 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 20, 2026 12:55 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:32 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:32 — with GitHub Actions Inactive
gilgardosh and others added 7 commits July 21, 2026 18:33
* feat(mcp-server): scaffold package skeleton (Prompt 01)

Create packages/mcp-server with minimal TypeScript scaffolding and yarn
workspace scripts, following the incremental MCP build plan in
docs/mcp/implementation-blueprint.md.

- package.json with build/dev/lint/test/typecheck scripts
- tsconfig.json extending the monorepo base config
- package-local vitest config for isolated test runs
- src/index.ts no-op startup entrypoint
- placeholder scaffold test under src/__tests__

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

* fix(mcp-server): use fileURLToPath for direct-run detection

Address review: comparing import.meta.url to a hand-built file:// string is
fragile for paths with spaces/special chars (URL-encoded in import.meta.url).

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
* feat(mcp-server): strict environment config (Prompt 02)

Add a fail-fast, schema-validated environment configuration module for the
MCP server following docs/mcp/spec.md §14.

- src/config/env.ts: zod schema covering MCP host/port/enabled/allowlist,
  Auth0 issuer/audience/JWKS, and upstream GraphQL URL/timeout, with secure
  defaults and least-privilege empty tool allowlist
- pure, testable parseEnv() plus lazy memoized env accessor so importing the
  module is side-effect free while first access still fails fast
- unit tests for valid config, defaults, derivations, and invalid/missing vars
- env variable table documented in module comments and README

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

* fix(mcp-server): pass processEnv to dotenv so custom source is honored

Address review: dotenv mutates process.env by default; when loadEnv is called
with a custom source, populate that source instead.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
gilgardosh and others added 3 commits July 21, 2026 18:33
… Prompt 03) (#3953)

* feat(mcp-server): HTTP bootstrap with health and graceful shutdown (Prompt 03)

Stand up a minimal node:http server with a /health endpoint, graceful
shutdown, and top-level error handling — no MCP protocol logic yet.

- src/server.ts: stdlib HTTP server, GET /health returning
  status/service/version/uptime, deterministic 404/500 routing, and a
  unit-testable createShutdownHandler for SIGINT/SIGTERM with a forced-exit
  grace period
- src/logger.ts: minimal single-line JSON structured logger
- src/index.ts: entrypoint installing uncaughtException/unhandledRejection
  handlers and starting the server with fatal-startup guarding
- tests for health, routing, version, and shutdown behavior

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

* fix(mcp-server): harden health version read, shutdown, and logger

Address review comments:
- cache the package.json version read (avoid sync disk I/O per /health request)
- close idle keep-alive connections during shutdown so it doesn't stall
- wrap logger serialization in try/catch (used inside global error handlers)

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
…t 04) (#3954)

* feat(mcp-server): MCP transport route with list-tools stub (Prompt 04)

Add the Streamable HTTP MCP endpoint (POST /mcp) speaking JSON-RPC 2.0, with
a request-dispatch skeleton and one internal smoke tool. Auth-agnostic and no
upstream GraphQL calls yet.

- src/mcp/jsonrpc.ts: minimal JSON-RPC 2.0 primitives, error codes, request
  validation
- src/mcp/tools.ts: internal-only accounter_smoke_ping descriptor + runner
- src/mcp/handler.ts: method dispatch (initialize, ping, tools/list,
  tools/call), deterministic method-not-found for unknown ops, bounded body
  reader, and the HTTP adapter (202 for notifications, 413 over cap)
- src/version.ts: shared service name/version helper (avoids server↔handler
  import cycle)
- server.ts: register POST /mcp and a deterministic 405 for GET /mcp
- tests covering dispatch, malformed input, and the HTTP adapter

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

* fix(mcp-server): harden MCP transport per review

Address review comments:
- tools/call with an unknown tool returns InvalidParams (-32602), not
  MethodNotFound — the method itself is supported
- validate JSON-RPC params is a structured value (object/array), never a
  primitive
- on oversized body, pause() the stream (not destroy) and set Connection:close
  + destroy after finish, so the 413 response is actually delivered
- cache the package.json version read in version.ts (avoid sync disk I/O per
  /health request)

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
#3970)

* feat(mcp-server): request context and structured request logging (Prompt 05)

Add observability groundwork per docs/mcp/spec.md §11.1.

- src/context.ts: per-request context with request id + correlation id
  (inherited from inbound X-Correlation-Id when present), method/route, and a
  latency timer; per-request context store via WeakMap
- src/logger.ts: context-bound request logger that stamps requestId,
  correlationId, method, and route on every entry; completion/latency helpers
- server.ts: mint context per request, echo X-Correlation-Id, and log request
  start/completion (status + latencyMs) and failures
- query strings and auth headers are never logged
- unit tests for context, logger, and correlation-id propagation

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

* fix(mcp-server): robust route parsing and completion logging

Address review comments:
- guard new URL() in createRequestContext so a malformed req.url falls back to
  a path split instead of throwing out of context creation (which would hang
  the request)
- log request completion on the response 'close' event (not 'finish') so an
  aborted/prematurely-closed connection still emits a completion log

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
github-actions Bot and others added 3 commits July 21, 2026 15:34
… 06) (#3971)

* feat(mcp-server): OAuth protected resource metadata route (Prompt 06)

Serve RFC 9728 protected-resource metadata so Claude clients can discover the
Auth0 authorization server (docs/mcp/spec.md §6.2).

- src/oauth/metadata.ts: config-driven buildProtectedResourceMetadata() and
  protectedResourceMetadataUrl() helpers; well-known path constant
- GET /.well-known/oauth-protected-resource returns { resource,
  authorization_servers, bearer_methods_supported: ["header"] } as JSON, with
  resource matching MCP_PUBLIC_BASE_URL exactly
- unit tests for the document shape + route-level test through requestHandler

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

* test(mcp-server): use vi.stubEnv for the metadata route test

Address review: stub env vars via vi.stubEnv/vi.unstubAllEnvs instead of
mutating process.env directly, to avoid cross-test pollution.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:41 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:41 — with GitHub Actions Inactive
… 07) (#3972)

* feat(mcp-server): 401 challenge helper for auth discovery (Prompt 07)

Add a standards-compliant unauthenticated response for MCP OAuth discovery
(docs/mcp/spec.md §6.2, §10.1) and gate the MCP endpoint on token presence.

- src/oauth/challenge.ts: buildWwwAuthenticateHeader() and sendUnauthorized()
  emitting 401 + WWW-Authenticate: Bearer with a resource_metadata pointer to
  the well-known document (transport-level, never a JSON-RPC/tool error)
- handler.ts: hasBearerToken() presence check; POST /mcp without a bearer
  token now returns the 401 challenge (token validity verified in Prompt 08)
- tests for the header builder, sendUnauthorized, the presence check, and the
  401 path through mcpHttpHandler

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

* fix(mcp-server): RFC-compliant WWW-Authenticate header

Address review:
- only emit error_description alongside error (RFC 6750 §3)
- escape " and \ in quoted-string parameter values (RFC 7235)
- use vi.stubEnv in the 401 handler test instead of mutating process.env

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:50 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 15:50 — with GitHub Actions Inactive
…rompt 08) (#3973)

* feat(mcp-server): bearer token extraction and Auth0 verification (Prompt 08)

Verify Auth0 access tokens on the MCP endpoint (docs/mcp/spec.md §6.4, §8/§10.1),
reusing the server package's jose-based JWKS approach.

- src/auth/token.ts: extractBearerToken(); verifyAccessTokenWithKey() enforcing
  issuer/audience/signature/expiry and mapping claims to a typed AuthPrincipal
  (subject, scopes from scope+permissions, email); TokenVerificationError
  carries no token material; per-request principal store
- src/auth/verifier.ts: env-backed verifyAccessToken() using a cached remote
  JWKS (createRemoteJWKSet) keyed by JWKS URL
- handler.ts: POST /mcp now extracts + verifies the token; invalid/expired ->
  401 with error="invalid_token"; missing -> 401 challenge; failures logged by
  reason only (never the token)
- add jose dependency; unit tests for extraction, claim mapping, and
  valid/wrong-issuer/wrong-audience/expired/wrong-key verification

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

* fix(mcp-server): don't mask JWKS/infra failures as 401; tidy principal types

Address review:
- verifyAccessTokenWithKey only wraps genuine token-validation errors (by jose
  error code) into TokenVerificationError; infrastructure failures (e.g. a JWKS
  fetch timeout) propagate so the request surfaces as a 5xx instead of a
  misleading 401
- handler.authenticate rethrows non-TokenVerificationError so those become 500
- use the AuthPrincipal type directly in the import and authenticate() return
  type instead of Awaited<ReturnType<...>>
- tests: infra error propagation at both the verifier and handler layers

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

* prettier

---------

Co-authored-by: Claude <noreply@anthropic.com>
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 16:03 — with GitHub Actions Inactive
@gilgardosh
gilgardosh temporarily deployed to accounter-fullstack July 21, 2026 16:03 — with GitHub Actions Inactive
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.

1 participant