@zigrivers/scaffold 3.32.1 → 3.33.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +41 -18
  2. package/content/guides/knowledge-freshness/.diagrams/diagram-0.svg +1 -1
  3. package/content/guides/knowledge-freshness/.diagrams/manifest.json +1 -1
  4. package/content/guides/knowledge-freshness/index.html +9 -5
  5. package/content/guides/knowledge-freshness/index.md +5 -4
  6. package/content/guides/pipeline/index.html +2 -2
  7. package/content/guides/pipeline/index.md +2 -2
  8. package/content/knowledge/VERSION +1 -1
  9. package/content/knowledge/backend/backend-api-design.md +21 -3
  10. package/content/knowledge/backend/backend-architecture.md +21 -3
  11. package/content/knowledge/backend/backend-async-patterns.md +16 -2
  12. package/content/knowledge/backend/backend-auth-patterns.md +19 -2
  13. package/content/knowledge/backend/backend-conventions.md +15 -3
  14. package/content/knowledge/backend/backend-data-modeling.md +19 -3
  15. package/content/knowledge/backend/backend-deployment.md +21 -3
  16. package/content/knowledge/backend/backend-dev-environment.md +13 -3
  17. package/content/knowledge/backend/backend-fintech-broker-integration.md +14 -2
  18. package/content/knowledge/backend/backend-fintech-compliance.md +23 -4
  19. package/content/knowledge/mcp-server/mcp-authentication.md +100 -0
  20. package/content/knowledge/mcp-server/mcp-deployment-patterns.md +119 -0
  21. package/content/knowledge/mcp-server/mcp-error-handling.md +131 -0
  22. package/content/knowledge/mcp-server/mcp-observability.md +125 -0
  23. package/content/knowledge/mcp-server/mcp-prompt-primitives.md +119 -0
  24. package/content/knowledge/mcp-server/mcp-protocol-fundamentals.md +130 -0
  25. package/content/knowledge/mcp-server/mcp-resource-design.md +111 -0
  26. package/content/knowledge/mcp-server/mcp-sdk-selection.md +136 -0
  27. package/content/knowledge/mcp-server/mcp-testing-strategies.md +127 -0
  28. package/content/knowledge/mcp-server/mcp-tool-design.md +125 -0
  29. package/content/knowledge/mcp-server/mcp-transport-patterns.md +122 -0
  30. package/content/knowledge/mcp-server/mcp-versioning.md +115 -0
  31. package/content/methodology/custom-defaults.yml +2 -0
  32. package/content/methodology/deep.yml +2 -0
  33. package/content/methodology/mcp-server-overlay.yml +88 -0
  34. package/content/methodology/mvp.yml +2 -0
  35. package/content/pipeline/build/multi-agent-resume.md +107 -11
  36. package/content/pipeline/build/multi-agent-start.md +104 -11
  37. package/content/pipeline/build/single-agent-resume.md +74 -8
  38. package/content/pipeline/build/single-agent-start.md +69 -12
  39. package/content/pipeline/finalization/materialize-plan-to-beads.md +473 -0
  40. package/content/pipeline/foundation/beads.md +6 -0
  41. package/content/pipeline/planning/implementation-plan-review.md +25 -0
  42. package/content/pipeline/planning/implementation-plan.md +75 -1
  43. package/content/pipeline/specification/mcp-tool-resource-contract.md +77 -0
  44. package/dist/cli/commands/adopt.d.ts.map +1 -1
  45. package/dist/cli/commands/adopt.js +33 -1
  46. package/dist/cli/commands/adopt.js.map +1 -1
  47. package/dist/cli/commands/init.d.ts +6 -0
  48. package/dist/cli/commands/init.d.ts.map +1 -1
  49. package/dist/cli/commands/init.js +46 -3
  50. package/dist/cli/commands/init.js.map +1 -1
  51. package/dist/cli/init-flag-families.d.ts +6 -1
  52. package/dist/cli/init-flag-families.d.ts.map +1 -1
  53. package/dist/cli/init-flag-families.js +59 -2
  54. package/dist/cli/init-flag-families.js.map +1 -1
  55. package/dist/cli/init-flag-families.test.js +86 -1
  56. package/dist/cli/init-flag-families.test.js.map +1 -1
  57. package/dist/config/schema.d.ts +2310 -126
  58. package/dist/config/schema.d.ts.map +1 -1
  59. package/dist/config/schema.js +26 -1
  60. package/dist/config/schema.js.map +1 -1
  61. package/dist/config/schema.test.js +75 -2
  62. package/dist/config/schema.test.js.map +1 -1
  63. package/dist/config/validators/index.d.ts.map +1 -1
  64. package/dist/config/validators/index.js +2 -0
  65. package/dist/config/validators/index.js.map +1 -1
  66. package/dist/config/validators/mcp-server.d.ts +4 -0
  67. package/dist/config/validators/mcp-server.d.ts.map +1 -0
  68. package/dist/config/validators/mcp-server.js +37 -0
  69. package/dist/config/validators/mcp-server.js.map +1 -0
  70. package/dist/config/validators/mcp-server.test.d.ts +2 -0
  71. package/dist/config/validators/mcp-server.test.d.ts.map +1 -0
  72. package/dist/config/validators/mcp-server.test.js +47 -0
  73. package/dist/config/validators/mcp-server.test.js.map +1 -0
  74. package/dist/core/assembly/materialize-plan-to-beads-assembly.test.d.ts +2 -0
  75. package/dist/core/assembly/materialize-plan-to-beads-assembly.test.d.ts.map +1 -0
  76. package/dist/core/assembly/materialize-plan-to-beads-assembly.test.js +75 -0
  77. package/dist/core/assembly/materialize-plan-to-beads-assembly.test.js.map +1 -0
  78. package/dist/e2e/project-type-overlays.test.js +83 -0
  79. package/dist/e2e/project-type-overlays.test.js.map +1 -1
  80. package/dist/project/adopt.d.ts.map +1 -1
  81. package/dist/project/adopt.js +3 -1
  82. package/dist/project/adopt.js.map +1 -1
  83. package/dist/project/detectors/coverage.test.js +1 -0
  84. package/dist/project/detectors/coverage.test.js.map +1 -1
  85. package/dist/project/detectors/disambiguate.d.ts.map +1 -1
  86. package/dist/project/detectors/disambiguate.js +6 -1
  87. package/dist/project/detectors/disambiguate.js.map +1 -1
  88. package/dist/project/detectors/disambiguate.test.js +18 -0
  89. package/dist/project/detectors/disambiguate.test.js.map +1 -1
  90. package/dist/project/detectors/index.d.ts.map +1 -1
  91. package/dist/project/detectors/index.js +2 -1
  92. package/dist/project/detectors/index.js.map +1 -1
  93. package/dist/project/detectors/mcp-server.d.ts +4 -0
  94. package/dist/project/detectors/mcp-server.d.ts.map +1 -0
  95. package/dist/project/detectors/mcp-server.js +91 -0
  96. package/dist/project/detectors/mcp-server.js.map +1 -0
  97. package/dist/project/detectors/mcp-server.test.d.ts +2 -0
  98. package/dist/project/detectors/mcp-server.test.d.ts.map +1 -0
  99. package/dist/project/detectors/mcp-server.test.js +115 -0
  100. package/dist/project/detectors/mcp-server.test.js.map +1 -0
  101. package/dist/project/detectors/types.d.ts +6 -2
  102. package/dist/project/detectors/types.d.ts.map +1 -1
  103. package/dist/project/detectors/types.js.map +1 -1
  104. package/dist/types/config.d.ts +8 -1
  105. package/dist/types/config.d.ts.map +1 -1
  106. package/dist/wizard/copy/core.d.ts.map +1 -1
  107. package/dist/wizard/copy/core.js +4 -0
  108. package/dist/wizard/copy/core.js.map +1 -1
  109. package/dist/wizard/copy/index.d.ts.map +1 -1
  110. package/dist/wizard/copy/index.js +2 -0
  111. package/dist/wizard/copy/index.js.map +1 -1
  112. package/dist/wizard/copy/mcp-server.d.ts +3 -0
  113. package/dist/wizard/copy/mcp-server.d.ts.map +1 -0
  114. package/dist/wizard/copy/mcp-server.js +40 -0
  115. package/dist/wizard/copy/mcp-server.js.map +1 -0
  116. package/dist/wizard/copy/types.d.ts +5 -1
  117. package/dist/wizard/copy/types.d.ts.map +1 -1
  118. package/dist/wizard/flags.d.ts +9 -1
  119. package/dist/wizard/flags.d.ts.map +1 -1
  120. package/dist/wizard/questions.d.ts +4 -2
  121. package/dist/wizard/questions.d.ts.map +1 -1
  122. package/dist/wizard/questions.js +37 -0
  123. package/dist/wizard/questions.js.map +1 -1
  124. package/dist/wizard/questions.test.js +107 -0
  125. package/dist/wizard/questions.test.js.map +1 -1
  126. package/dist/wizard/wizard.d.ts +3 -2
  127. package/dist/wizard/wizard.d.ts.map +1 -1
  128. package/dist/wizard/wizard.js +3 -1
  129. package/dist/wizard/wizard.js.map +1 -1
  130. package/package.json +1 -1
@@ -1,13 +1,25 @@
1
1
  ---
2
2
  name: backend-fintech-broker-integration
3
3
  description: Multi-broker adapter pattern; credential rotation; error harmonization; rate-limit management; broker-side quirks.
4
- topics: [backend, fintech, brokers, integration, adapter-pattern, rate-limits, credentials, retry]
4
+ topics:
5
+ - backend
6
+ - fintech
7
+ - brokers
8
+ - integration
9
+ - adapter-pattern
10
+ - rate-limits
11
+ - credentials
12
+ - retry
5
13
  volatility: evolving
6
- last-reviewed: null
14
+ last-reviewed: 2025-04-08
7
15
  version-pin: null
8
16
  sources:
9
17
  - url: https://microservices.io/patterns/reliability/circuit-breaker.html
18
+ hash: sha256:a117f72fc0d279ea99d4234ea8a8cc7bdf23d7ed59d94effc6129d613518a6fa
19
+ retrieved: 2025-04-08
10
20
  - url: https://martinfowler.com/bliki/CircuitBreaker.html
21
+ hash: sha256:73239948ec03887430a4d139e384e94bc640fec894fb1dce53b56abe579c5da4
22
+ retrieved: 2025-04-08
11
23
  ---
12
24
 
13
25
  A fintech backend that routes orders or reads positions across more than one broker inherits the union of every broker's quirks, outages, auth schemes, and undocumented behaviors. The broker-integration layer exists to hide that mess behind one normalized internal contract so the rest of the system — risk, order lifecycle, ledger, UI — can stay clean. This doc covers the adapter contract, credential handling, error harmonization, rate-limit strategy, and the specific pitfalls that recur regardless of which brokers you connect.
@@ -1,15 +1,34 @@
1
1
  ---
2
2
  name: backend-fintech-compliance
3
- description: PCI-DSS, SOC 2, SEC/FINRA regulations for consumer/B2B fintech backends; audit trail immutability; data retention; segregation of duties.
4
- topics: [backend, fintech, compliance, pci-dss, soc2, sec, finra, audit-trail, gdpr]
3
+ description: >-
4
+ PCI-DSS, SOC 2, SEC/FINRA regulations for consumer/B2B fintech backends; audit trail immutability; data retention;
5
+ segregation of duties.
6
+ topics:
7
+ - backend
8
+ - fintech
9
+ - compliance
10
+ - pci-dss
11
+ - soc2
12
+ - sec
13
+ - finra
14
+ - audit-trail
15
+ - gdpr
5
16
  volatility: evolving
6
- last-reviewed: null
7
- version-pin: 'PCI-DSS v4.0.1'
17
+ last-reviewed: 2025-06-01
18
+ version-pin: PCI-DSS v4.0.1
8
19
  sources:
9
20
  - url: https://www.pcisecuritystandards.org/document_library/
21
+ hash: sha256:9cb04202115fe2c3275274d93a4eb506c0f97648af0dcee12dc1da0faec0bcbf
22
+ retrieved: 2025-06-01
10
23
  - url: https://www.aicpa-cima.com/topic/audit-assurance
24
+ hash: sha256:08d2df6fd46adb5e0c62200435b8619d9dd67228ef1c9ce5cbe19e87f048a667
25
+ retrieved: 2025-06-01
11
26
  - url: https://www.finra.org/rules-guidance/rulebooks/finra-rules
27
+ hash: sha256:0ddd688189c919aeb3903adf06a0a727b515c9a51482c62bf9fdb77f53980e14
28
+ retrieved: 2025-06-01
12
29
  - url: https://eur-lex.europa.eu/eli/reg/2016/679/oj
30
+ hash: sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
31
+ retrieved: 2025-06-01
13
32
  ---
14
33
 
15
34
  Fintech compliance is not a checklist applied at the end — it determines schema design, deployment pipelines, and system boundaries. Most regulations apply based on what a service *touches* (cards, trades, PII), so scope reduction is the single highest-leverage design decision available to engineering. This doc covers the regulatory regimes a typical US/EU fintech encounters, the audit-trail patterns they demand, and concrete implementation choices that keep audits survivable.
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: mcp-authentication
3
+ description: MCP authentication patterns — stdio local trust model, OAuth 2.1 for HTTP transports, PKCE, dynamic client registration, API key alternatives, and token validation
4
+ topics: [mcp, authentication, oauth, security, authorization]
5
+ volatility: evolving
6
+ last-reviewed: null
7
+ version-pin: 'MCP spec 2025-11-25; OAuth 2.1 draft-ietf-oauth-v2-1-13'
8
+ sources:
9
+ - url: https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization
10
+ - url: https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-13
11
+ - url: https://datatracker.ietf.org/doc/html/rfc7591
12
+ - url: https://www.rfc-editor.org/rfc/rfc8707.html
13
+ ---
14
+
15
+ Authentication in MCP is transport-dependent. stdio servers rely on OS process isolation (no network auth needed). HTTP servers should use OAuth 2.1 for multi-user or multi-tenant scenarios, or simpler API key patterns for internal/single-tenant deployments.
16
+
17
+ ## Summary
18
+
19
+ **stdio transport**: no network authentication — the server inherits credentials from environment variables and the OS controls process access. **Streamable HTTP transport**: use OAuth 2.1 (per spec) for public or multi-user servers. OAuth flow: client hits protected resource, gets 401 with `WWW-Authenticate`, discovers authorization server via OAuth Protected Resource Metadata, completes OAuth 2.1 with PKCE, presents `Bearer` token on all subsequent requests. For simpler deployments, API keys in headers or environment-injected tokens are practical alternatives. The spec mandates `MCP-Protocol-Version` on HTTP requests and audience validation on tokens.
20
+
21
+ ## Deep Guidance
22
+
23
+ ### stdio: local trust model
24
+
25
+ The stdio transport requires no network authentication. Trust is established by OS-level process ownership: the client spawns the server as a subprocess, which means both run under the same user account. The server process inherits environment variables from the parent, which is the standard mechanism for passing API keys, database credentials, or access tokens to a local MCP server:
26
+
27
+ ```json
28
+ {
29
+ "mcpServers": {
30
+ "my-server": {
31
+ "command": "npx",
32
+ "args": ["my-mcp-server"],
33
+ "env": {
34
+ "DATABASE_URL": "postgresql://localhost/mydb",
35
+ "API_KEY": "sk-..."
36
+ }
37
+ }
38
+ }
39
+ }
40
+ ```
41
+
42
+ The spec is explicit: implementations using stdio SHOULD NOT follow the OAuth specification and SHOULD instead retrieve credentials from the environment. Do not add HTTP authentication middleware to a stdio server.
43
+
44
+ ### OAuth 2.1 for HTTP transports
45
+
46
+ For Streamable HTTP servers accessible over a network, the spec defines an OAuth 2.1 authorization flow. The server acts as an OAuth 2.1 **resource server**; a separate authorization server handles token issuance.
47
+
48
+ **Discovery flow (updated in 2025-11-25 per RFC 9728 and OIDC Discovery 1.0):**
49
+ 1. Client sends an unauthenticated MCP request.
50
+ 2. Server MAY respond `401 Unauthorized` with a `WWW-Authenticate` header pointing to the resource server metadata URL; however, the `WWW-Authenticate` header is now OPTIONAL — clients MUST fall back to fetching `/.well-known/oauth-protected-resource` directly if no header is present.
51
+ 3. Client fetches `/.well-known/oauth-protected-resource` (RFC 9728) to get the authorization server URL.
52
+ 4. Client fetches the authorization server's metadata. Authorization servers that support OpenID Connect SHOULD publish an OIDC Discovery document (`/.well-known/openid-configuration`) in addition to `/.well-known/oauth-authorization-server`.
53
+ 5. Client completes the OAuth 2.1 authorization code flow with PKCE. Clients SHOULD use OAuth Client ID Metadata Documents (a recommended client registration mechanism in 2025-11-25) where supported by the authorization server.
54
+ 6. Client presents `Authorization: Bearer <token>` on all subsequent requests. Servers MAY issue incremental scope consent via the `WWW-Authenticate` header on subsequent `403` responses.
55
+
56
+ **PKCE is mandatory** for public clients (MCP clients cannot keep secrets). The authorization server MUST support PKCE. The client generates a `code_verifier` (random string), hashes it to `code_challenge`, includes the challenge in the authorization request, and presents the verifier in the token request.
57
+
58
+ **Resource parameter** (RFC 8707): clients MUST include a `resource` parameter in both authorization and token requests identifying the MCP server's canonical URI (e.g., `https://mcp.example.com`). This binds tokens to their intended audience and prevents cross-service token reuse.
59
+
60
+ ### Token validation requirements
61
+
62
+ MCP servers MUST validate every incoming access token:
63
+ - Verify the token is valid and not expired.
64
+ - Verify the token's audience claim identifies this server (matches the server's canonical URI).
65
+ - Reject tokens with `401` if invalid or expired; `403` if the token is valid but lacks required scope.
66
+
67
+ NEVER accept tokens issued for a different resource. NEVER forward a received token to an upstream API — issue a separate token for each upstream call. Token passthrough is explicitly forbidden by the spec and creates confused deputy vulnerabilities.
68
+
69
+ ### Dynamic client registration
70
+
71
+ Authorization servers and clients SHOULD support OAuth 2.0 Dynamic Client Registration (RFC 7591). As of 2025-11-25, OAuth Client ID Metadata Documents are the recommended client registration mechanism — they allow clients to declare their identity via a URL rather than requiring a registration round-trip. Without dynamic registration support, MCP clients must be pre-registered with every authorization server, which creates friction for discovering and connecting to new servers. Dynamic registration lets a client auto-register on first connection:
72
+
73
+ ```
74
+ POST /register
75
+ { "client_name": "Claude Desktop", "redirect_uris": ["http://localhost:57842/callback"] }
76
+ → { "client_id": "abc123", ... }
77
+ ```
78
+
79
+ If the authorization server does not support dynamic registration, the client must hardcode a client ID or present a UI for manual credential entry.
80
+
81
+ ### Simpler alternatives for private/internal deployments
82
+
83
+ For servers used only within a controlled environment (team tool, internal service), full OAuth is often unnecessary overhead. Practical alternatives:
84
+
85
+ **API key in header**: The client includes a static API key in a custom header or as a Bearer token. The server validates it against a stored secret. Simple, easy to rotate, no token exchange flow.
86
+
87
+ **Mutual TLS**: Suitable for service-to-service scenarios where both sides have certificates. The TLS handshake authenticates both parties.
88
+
89
+ **Reverse proxy with auth**: Run the MCP server behind nginx/Caddy/Cloudflare with authentication handled at the proxy layer. The server itself trusts all proxied connections.
90
+
91
+ **Network isolation**: For truly internal deployments, rely on network controls (VPN, private subnet, firewall rules) and skip application-layer auth. Acceptable only when the network boundary is the full security boundary.
92
+
93
+ ### Security hardening checklist
94
+
95
+ - Validate the `Origin` header on all Streamable HTTP connections to prevent DNS rebinding attacks.
96
+ - Use HTTPS for all HTTP transport connections (required by OAuth 2.1 for authorization server endpoints and redirect URIs).
97
+ - Bind local HTTP servers to 127.0.0.1, not 0.0.0.0.
98
+ - Rotate API keys and tokens regularly; issue short-lived access tokens.
99
+ - Log all authentication failures with enough context to diagnose attacks.
100
+ - Do not embed credentials in resource URIs (they appear in logs and referrer headers).
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: mcp-deployment-patterns
3
+ description: MCP server deployment — local stdio subprocess, hosted container/serverless, lifecycle management, environment config, and operational patterns for each deployment model
4
+ topics: [mcp, deployment, stdio, container, serverless, operations]
5
+ volatility: evolving
6
+ last-reviewed: null
7
+ version-pin: null
8
+ sources:
9
+ - url: https://modelcontextprotocol.io/specification/2025-11-25/basic/transports
10
+ - url: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
11
+ - url: https://modelcontextprotocol.io/docs/develop/connect-local-servers
12
+ ---
13
+
14
+ MCP server deployment splits into two fundamentally different models: local subprocess (stdio) installed on the user's machine, and hosted service (container or serverless) running independently. Each has different lifecycle, configuration, update, and security characteristics.
15
+
16
+ ## Summary
17
+
18
+ **Local stdio deployment**: server is installed as a CLI tool (npm package, Python package, binary) and launched as a subprocess by the client. Configuration lives in the client's server registry (e.g., `claude_desktop_config.json`). Updates require reinstalling the package. Lifecycle is tied to the client process. **Hosted deployment**: server runs as a persistent HTTP service, deployed to a container host or serverless platform. Clients connect via Streamable HTTP. Supports multiple concurrent users, centralized updates, and independent scaling. Use `stdio` for local developer tools; use hosted deployment for shared team/organization servers.
19
+
20
+ ## Deep Guidance
21
+
22
+ ### Local stdio deployment
23
+
24
+ The stdio model packages the MCP server as an installable CLI tool. The user installs it once; each MCP client registers it in its server configuration:
25
+
26
+ ```json
27
+ {
28
+ "mcpServers": {
29
+ "filesystem": {
30
+ "command": "npx",
31
+ "args": ["-y", "@modelcontextprotocol/server-filesystem", "/Users/alice/projects"],
32
+ "env": {
33
+ "NODE_ENV": "production"
34
+ }
35
+ },
36
+ "mydb": {
37
+ "command": "uvx",
38
+ "args": ["mcp-server-postgres"],
39
+ "env": {
40
+ "DATABASE_URL": "postgresql://localhost/mydb"
41
+ }
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ **Package distribution**: Publish to npm (`npx`-runnable) for TypeScript/Node.js servers; publish to PyPI (`uvx`-runnable) for Python servers. `npx -y` and `uvx` auto-install on first run, minimizing setup friction. For compiled binaries (Go, Rust), distribute via Homebrew, Winget, or direct download.
48
+
49
+ **Configuration**: Pass per-installation config via `env` (preferred) or `args`. Avoid config files with relative paths — the working directory is undefined when launched by a client (it could be `/` or the client's install directory). Always use absolute paths for any file references.
50
+
51
+ **Credentials**: Pass API keys and secrets via `env`, never via `args` (args appear in process listings). The client's server configuration file must be protected with appropriate file permissions.
52
+
53
+ **Lifecycle**: The client spawns the server on first use and keeps the process alive while connected. On shutdown, the client closes stdin and waits for the server to exit. Implement a clean shutdown handler: flush any pending state, close database connections, release file locks. In Node.js: listen for `SIGTERM`. In Python: implement `atexit` handlers or use FastMCP's lifecycle hooks. The server MUST exit cleanly after stdin is closed — a server that hangs will be forcibly killed.
54
+
55
+ **Updates**: Users update by reinstalling (`npm update -g my-server`, `uv tool upgrade my-server`). Pin your client in the MCP server registry to exact versions for stability-critical tools; use range specifiers for tools that benefit from automatic minor updates.
56
+
57
+ ### Hosted container deployment
58
+
59
+ Containerized MCP servers run as long-lived HTTP services behind a container orchestrator (Docker Compose, Kubernetes, ECS, Cloud Run):
60
+
61
+ ```dockerfile
62
+ FROM node:22-alpine
63
+ WORKDIR /app
64
+ COPY package*.json ./
65
+ RUN npm ci --production
66
+ COPY dist/ ./dist/
67
+ EXPOSE 3000
68
+ CMD ["node", "dist/index.js"]
69
+ ```
70
+
71
+ The server uses the Streamable HTTP transport:
72
+ ```typescript
73
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'
74
+ import express from 'express'
75
+
76
+ const app = express()
77
+ app.use(express.json())
78
+
79
+ const transport = new StreamableHTTPServerTransport({ endpoint: '/mcp' })
80
+ await server.connect(transport)
81
+
82
+ app.all('/mcp', (req, res) => transport.handle(req, res))
83
+ app.listen(3000)
84
+ ```
85
+
86
+ **Health checks**: expose a `/health` or `/ping` endpoint that returns 200 when the server is ready. Container orchestrators use this to route traffic only to healthy instances.
87
+
88
+ **Configuration**: inject secrets via environment variables (Kubernetes Secrets, AWS Parameter Store, Vault). Never bake credentials into container images.
89
+
90
+ **Graceful shutdown**: listen for `SIGTERM` (sent by orchestrators before `SIGKILL`). Drain in-flight requests, close upstream connections, then exit. Typical drain window: 10–30 seconds.
91
+
92
+ ### Serverless deployment
93
+
94
+ Serverless (AWS Lambda, Google Cloud Functions, Vercel Edge) works for stateless MCP servers using Streamable HTTP. The primary constraint: serverless functions are stateless across invocations, so session state must be stored externally (Redis, DynamoDB) if you support `Mcp-Session-Id`.
95
+
96
+ For fully stateless servers (each request is independent, no subscriptions, no session-dependent state), serverless works well:
97
+ - Keep cold start time under 1 second (avoid large imports, use lazy initialization).
98
+ - Set function timeout generously (MCP tool calls that invoke slow APIs may need 30+ seconds).
99
+ - Disable or carefully manage resource subscriptions — subscription state cannot survive function restarts without external storage.
100
+
101
+ ### Multi-user stdio: local multiplexing
102
+
103
+ Some deployment environments need multiple users to share a single MCP server installation without a hosted service. Options:
104
+ - **Per-user install**: each user installs and configures the server independently. Simplest, most isolated.
105
+ - **System-wide daemon**: run the MCP server as a system service over a Unix domain socket, with per-user authentication at the socket level. Complex but enables centralized configuration and single-instance resource use.
106
+
107
+ For most teams, a hosted HTTP deployment is simpler than system-level socket multiplexing.
108
+
109
+ ### Choosing deployment model
110
+
111
+ | Requirement | Recommended model |
112
+ |-------------|------------------|
113
+ | Local file access (user's files) | Local stdio |
114
+ | Developer CLI wrapper | Local stdio |
115
+ | Shared team knowledge base | Hosted container |
116
+ | SaaS integration (multi-tenant) | Hosted container or serverless |
117
+ | Real-time resource subscriptions | Hosted container (stateful) |
118
+ | Zero-infrastructure setup | Local stdio |
119
+ | SOC2/compliance audit trail | Hosted container |
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: mcp-error-handling
3
+ description: MCP protocol errors (JSON-RPC error codes) vs tool execution errors (isError content), partial failures, error message design, and client recovery patterns
4
+ topics: [mcp, error-handling, json-rpc, tool-errors, protocol-errors]
5
+ volatility: evolving
6
+ last-reviewed: null
7
+ version-pin: 'MCP spec 2025-11-25'
8
+ sources:
9
+ - url: https://modelcontextprotocol.io/specification/2025-11-25/server/tools
10
+ - url: https://modelcontextprotocol.io/specification/2025-11-25/basic/lifecycle
11
+ - url: https://www.jsonrpc.org/specification
12
+ ---
13
+
14
+ MCP has two distinct error channels. Mixing them up is one of the most common MCP server bugs: using protocol errors for domain failures causes the LLM to lose context about what went wrong; using isError for protocol failures breaks client error-handling logic.
15
+
16
+ ## Summary
17
+
18
+ **Protocol errors** (JSON-RPC error responses) signal that a request could not be processed at all — unknown method, invalid parameters, server crash. Use standard JSON-RPC error codes. **Tool execution errors** (`isError: true` in the tool result) signal that the tool ran but the operation failed — API error, resource not found, business logic rejection. The LLM can read and react to tool errors; it cannot generally recover from protocol errors. Always prefer `isError: true` for domain-level failures that a well-behaved caller might encounter.
19
+
20
+ ## Deep Guidance
21
+
22
+ ### Protocol errors: JSON-RPC error responses
23
+
24
+ A protocol error is a JSON-RPC error response object. It replaces the `result` field entirely:
25
+
26
+ ```json
27
+ {
28
+ "jsonrpc": "2.0",
29
+ "id": 3,
30
+ "error": {
31
+ "code": -32602,
32
+ "message": "Unknown tool: invalid_tool_name"
33
+ }
34
+ }
35
+ ```
36
+
37
+ Use protocol errors for:
38
+ - **Method not found** (`-32601`): the client called a method the server does not implement.
39
+ - **Invalid params** (`-32602`): structural/wire-level request problems that prevent dispatch entirely — unknown tool name in `tools/call`, unknown method, missing required prompt arguments to `prompts/get`, invalid resource URI in `resources/read`, malformed params shape at the JSON-RPC level. **Do NOT use `-32602` for a tool that dispatched successfully but whose arguments fail the tool's own `inputSchema` or business validation** — those are tool execution errors (see `isError` below).
40
+ - **Internal error** (`-32603`): unhandled exception or server bug. Include enough detail in `message` to diagnose, but sanitize sensitive data.
41
+ - **Parse error** (`-32700`): malformed JSON received. The SDK handles this automatically.
42
+ - **Invalid request** (`-32600`): request is not valid JSON-RPC 2.0 structure. Also SDK-handled.
43
+
44
+ Custom server-defined error codes MUST be in the JSON-RPC server-error range `-32099` to `-32000` (most-negative to least-negative). Standard resource error code: `-32002` (resource not found).
45
+
46
+ The `error` object MAY include a `data` field with additional structured context:
47
+ ```json
48
+ {
49
+ "code": -32602,
50
+ "message": "Missing required argument",
51
+ "data": { "argument": "location", "required": true }
52
+ }
53
+ ```
54
+
55
+ ### Tool execution errors: isError
56
+
57
+ When a tool runs but the operation it performs fails, return the failure as a normal result with `isError: true`:
58
+
59
+ ```json
60
+ {
61
+ "jsonrpc": "2.0",
62
+ "id": 4,
63
+ "result": {
64
+ "content": [
65
+ {
66
+ "type": "text",
67
+ "text": "Failed to fetch weather data: API returned 429 Too Many Requests. Rate limit resets at 14:00 UTC. Suggest retrying after that time."
68
+ }
69
+ ],
70
+ "isError": true
71
+ }
72
+ }
73
+ ```
74
+
75
+ Use `isError: true` for:
76
+ - **Tool input/schema validation failures** — when a tool dispatches but its arguments fail the tool's own `inputSchema` or business validation rules (wrong value, out-of-range number, unsupported enum value, failed cross-field constraint). Per SEP-1303 (2025-11-25), these MUST be `isError: true` so the model can self-correct, NOT `-32602`.
77
+ - External API failures (HTTP 4xx/5xx from downstream services)
78
+ - Resource not found in a domain sense (file doesn't exist at the path the user specified)
79
+ - Business logic rejections (insufficient permissions in the target system, invalid state for the operation)
80
+ - Network timeouts when calling downstream services
81
+ - Partial failures where the overall result is a failure
82
+
83
+ **Why this distinction matters**: when `isError: true`, the result is a successful JSON-RPC response — the protocol layer worked correctly. The LLM receives the content and can read the error message, decide to retry with different parameters, inform the user, or take an alternative approach. Protocol errors, on the other hand, are invisible to the LLM in most client implementations — they're handled at the transport/client layer. The 2025-11-25 spec revision (SEP-1303) explicitly directs that tool input validation errors MUST be returned as Tool Execution Errors (`isError: true`) rather than Protocol Errors (`-32602`), specifically to enable model self-correction. This applies to any argument that dispatches to a real tool but fails schema/business validation once there.
84
+
85
+ ### Error message quality
86
+
87
+ Both protocol error messages and `isError` content messages are read by either developers (protocol errors) or LLMs (isError). Write them to be actionable:
88
+
89
+ **For isError messages** (LLM-readable):
90
+ - State what failed specifically, not just "an error occurred".
91
+ - Include any relevant IDs, timestamps, or context the LLM can use.
92
+ - Suggest what to do next when recovery is possible.
93
+ - Include rate limit reset times, retry suggestions, or alternative approaches.
94
+
95
+ **For protocol error messages** (developer-readable):
96
+ - Name the specific field or method that caused the error.
97
+ - Quote the invalid value or describe the expected format.
98
+ - Avoid exposing internal file paths, stack traces, or secrets.
99
+
100
+ ### Partial failures in multi-item operations
101
+
102
+ When a tool processes multiple items and some succeed while others fail:
103
+
104
+ **Option A (partial success)**: Return successful results and error descriptions in the `content` array, without setting `isError: true`. Use this when partial output is useful:
105
+ ```json
106
+ {
107
+ "content": [
108
+ { "type": "text", "text": "Processed 3 of 5 items:\n✓ item1: success\n✓ item2: success\n✗ item3: rate limited\n✓ item4: success\n✗ item5: not found" }
109
+ ]
110
+ }
111
+ ```
112
+
113
+ **Option B (total failure)**: If no items succeeded or the partial result is not useful, set `isError: true` and describe the failure.
114
+
115
+ Never silently drop failures — always include what failed and why, even in partial success responses.
116
+
117
+ ### Initialization and lifecycle errors
118
+
119
+ During the `initialize` handshake, return a protocol error if:
120
+ - The client requests a protocol version the server does not support (respond with your supported version per spec, or error if incompatible).
121
+ - Required capabilities cannot be negotiated.
122
+
123
+ After initialization, if a client calls a method whose capability was not declared (e.g., calls `tools/list` but the server did not declare `tools` capability), return `-32601` (method not found) or `-32602` (invalid params) to indicate the feature is not available.
124
+
125
+ ### Client-side recovery patterns
126
+
127
+ MCP clients should handle these error patterns from servers:
128
+ - **Protocol error on tool call**: log the error, surface to user if relevant, do not retry automatically (likely a programming error).
129
+ - **`isError: true` on tool result**: pass the error content to the LLM — it can decide whether to retry, use a different tool, or report to the user.
130
+ - **Server disconnect / connection reset**: attempt reconnection and re-run the `initialize` handshake before resuming operations. Do not silently drop in-flight requests.
131
+ - **`notifications/tools/list_changed`**: re-issue `tools/list` before the next tool call to ensure the cached tool list is current.
@@ -0,0 +1,125 @@
1
+ ---
2
+ name: mcp-observability
3
+ description: MCP server structured logging, stderr discipline for stdio transport, log message notifications, request tracing, debugging with MCP Inspector, and performance monitoring
4
+ topics: [mcp, observability, logging, tracing, debugging, monitoring]
5
+ volatility: evolving
6
+ last-reviewed: null
7
+ version-pin: null
8
+ sources:
9
+ - url: https://modelcontextprotocol.io/docs/tools/debugging
10
+ - url: https://modelcontextprotocol.io/specification/2025-11-25/server/utilities/logging
11
+ ---
12
+
13
+ Good observability in an MCP server means you can diagnose problems without attaching a debugger. The fundamental constraint is the stdio transport's stdout-is-protocol-only rule, which makes naive logging dangerous. Structured logging to the right channel is non-negotiable.
14
+
15
+ ## Summary
16
+
17
+ For **stdio servers**, write all logging to **stderr** — stdout is reserved exclusively for JSON-RPC protocol messages. Any stray write to stdout corrupts the protocol stream. For **HTTP servers**, use standard structured logging to files, stdout, or an aggregator — stderr is not captured by clients. MCP also provides a protocol-level logging mechanism via `notifications/message` (usable on any transport). Always include a correlation ID per request. Use the MCP Inspector as your first debugging tool.
18
+
19
+ ## Deep Guidance
20
+
21
+ ### Stderr discipline for stdio transport
22
+
23
+ The stdio transport reserves stdout entirely for JSON-RPC protocol messages. Even a single line of non-JSON output to stdout — a startup banner, a debug print, a library that logs to stdout by default — will corrupt the message stream and cause parse errors in the client. This is the most common cause of "MCP server not responding" problems.
24
+
25
+ **TypeScript/Node.js**: use `process.stderr.write(...)` or a logging library configured to stderr:
26
+ ```typescript
27
+ import { createWriteStream } from 'node:fs'
28
+ // write to stderr or a log file — never process.stdout
29
+ const log = (msg: string) => process.stderr.write(`[server] ${msg}\n`)
30
+ ```
31
+
32
+ **Python**: use `print(..., file=sys.stderr)` or configure `logging` to use stderr:
33
+ ```python
34
+ import logging, sys
35
+ logging.basicConfig(
36
+ level=logging.INFO,
37
+ stream=sys.stderr, # critical: must be stderr, not stdout
38
+ format='%(asctime)s %(levelname)s %(name)s: %(message)s'
39
+ )
40
+ ```
41
+
42
+ The Python SDK's FastMCP does this correctly by default. Watch for third-party libraries that configure their own logging handlers pointing at stdout.
43
+
44
+ **Go**: `log.Println` writes to stderr by default — safe for stdio servers. Avoid `fmt.Println` which goes to stdout.
45
+
46
+ ### MCP protocol-level logging (all transports)
47
+
48
+ For any transport, the server can send log messages to the client via the `notifications/message` notification. The server must declare `logging: {}` in its capabilities during initialization.
49
+
50
+ Log levels follow RFC 5424: `debug`, `info`, `notice`, `warning`, `error`, `critical`, `alert`, `emergency`. Clients can set the minimum level via `logging/setLevel`.
51
+
52
+ TypeScript SDK:
53
+ ```typescript
54
+ await server.sendLoggingMessage({ level: 'info', data: 'Tool execution started', logger: 'weather-tool' })
55
+ ```
56
+
57
+ Python FastMCP:
58
+ ```python
59
+ await ctx.session.send_log_message(level="info", data="Processing request", logger="my-server")
60
+ ```
61
+
62
+ Protocol-level logging is visible to the MCP client (and to the Inspector's Notifications pane), making it useful for surfacing server state to the host application without relying on stderr capture.
63
+
64
+ ### Structured logging format
65
+
66
+ Use structured logs (JSON or key=value) rather than unstructured strings. Include:
67
+ - `timestamp`: ISO 8601 or epoch milliseconds
68
+ - `level`: debug/info/warning/error
69
+ - `request_id` or `correlation_id`: unique per MCP request (use the JSON-RPC `id` field value)
70
+ - `method`: the JSON-RPC method being handled
71
+ - `tool_name` / `resource_uri` / `prompt_name`: the specific capability invoked
72
+ - `duration_ms`: time taken (for completed requests)
73
+ - `error`: error type and message (for failures)
74
+
75
+ Example structured log entry:
76
+ ```json
77
+ {
78
+ "timestamp": "2025-06-18T14:32:01.234Z",
79
+ "level": "info",
80
+ "request_id": "42",
81
+ "method": "tools/call",
82
+ "tool_name": "get_weather",
83
+ "duration_ms": 234,
84
+ "location": "New York"
85
+ }
86
+ ```
87
+
88
+ ### Request tracing
89
+
90
+ Assign a correlation ID to each incoming MCP request using the JSON-RPC `id` field (for requests) or a generated UUID (for notifications). Thread this ID through all log entries, downstream API calls, and database queries generated by that request. This makes it possible to reconstruct the full execution path for a single tool call when debugging a failure.
91
+
92
+ For HTTP transport, also include the `Mcp-Session-Id` in logs to correlate all requests within a session.
93
+
94
+ ### Debugging with MCP Inspector
95
+
96
+ The MCP Inspector is the most effective debugging tool for local development:
97
+
98
+ ```bash
99
+ # Launch your server with the Inspector
100
+ npx @modelcontextprotocol/inspector node dist/server.js
101
+ ```
102
+
103
+ Inspector debugging workflow:
104
+ 1. Check the Notifications pane for server log messages and error notifications.
105
+ 2. Invoke a failing tool and inspect the raw request/response in the tool result pane.
106
+ 3. Verify capability negotiation — check that the capabilities shown in the Inspector match what your server declares.
107
+ 4. Test error paths explicitly: call tools with invalid inputs and verify `isError: true` responses display correctly.
108
+
109
+ For Claude Desktop specifically, tail the MCP log files:
110
+ ```bash
111
+ # macOS
112
+ tail -F ~/Library/Logs/Claude/mcp*.log
113
+ ```
114
+
115
+ ### Performance monitoring
116
+
117
+ Log operation timing for all tool calls and resource reads. Track:
118
+ - **p50/p95/p99 latency** per tool: identify slow tools before users complain.
119
+ - **Error rate** per tool: high error rates indicate API instability or logic bugs.
120
+ - **Payload size**: large tool results consume LLM context; log result byte sizes to catch runaway responses.
121
+ - **Downstream API latency**: separately log time spent waiting for external APIs vs. server-side processing.
122
+
123
+ For HTTP-transport servers, standard HTTP middleware (Morgan, Express's req timing) captures request-level metrics. For stdio servers, implement timing within each tool handler and write to stderr/log file.
124
+
125
+ Set alerts on: error rate above 5%, tool latency p99 above 5 seconds, and any `SIGTERM` not followed by clean exit within 30 seconds (hung shutdown).