@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.
- package/README.md +41 -18
- package/content/guides/knowledge-freshness/.diagrams/diagram-0.svg +1 -1
- package/content/guides/knowledge-freshness/.diagrams/manifest.json +1 -1
- package/content/guides/knowledge-freshness/index.html +9 -5
- package/content/guides/knowledge-freshness/index.md +5 -4
- package/content/guides/pipeline/index.html +2 -2
- package/content/guides/pipeline/index.md +2 -2
- package/content/knowledge/VERSION +1 -1
- package/content/knowledge/backend/backend-api-design.md +21 -3
- package/content/knowledge/backend/backend-architecture.md +21 -3
- package/content/knowledge/backend/backend-async-patterns.md +16 -2
- package/content/knowledge/backend/backend-auth-patterns.md +19 -2
- package/content/knowledge/backend/backend-conventions.md +15 -3
- package/content/knowledge/backend/backend-data-modeling.md +19 -3
- package/content/knowledge/backend/backend-deployment.md +21 -3
- package/content/knowledge/backend/backend-dev-environment.md +13 -3
- package/content/knowledge/backend/backend-fintech-broker-integration.md +14 -2
- package/content/knowledge/backend/backend-fintech-compliance.md +23 -4
- package/content/knowledge/mcp-server/mcp-authentication.md +100 -0
- package/content/knowledge/mcp-server/mcp-deployment-patterns.md +119 -0
- package/content/knowledge/mcp-server/mcp-error-handling.md +131 -0
- package/content/knowledge/mcp-server/mcp-observability.md +125 -0
- package/content/knowledge/mcp-server/mcp-prompt-primitives.md +119 -0
- package/content/knowledge/mcp-server/mcp-protocol-fundamentals.md +130 -0
- package/content/knowledge/mcp-server/mcp-resource-design.md +111 -0
- package/content/knowledge/mcp-server/mcp-sdk-selection.md +136 -0
- package/content/knowledge/mcp-server/mcp-testing-strategies.md +127 -0
- package/content/knowledge/mcp-server/mcp-tool-design.md +125 -0
- package/content/knowledge/mcp-server/mcp-transport-patterns.md +122 -0
- package/content/knowledge/mcp-server/mcp-versioning.md +115 -0
- package/content/methodology/custom-defaults.yml +2 -0
- package/content/methodology/deep.yml +2 -0
- package/content/methodology/mcp-server-overlay.yml +88 -0
- package/content/methodology/mvp.yml +2 -0
- package/content/pipeline/build/multi-agent-resume.md +107 -11
- package/content/pipeline/build/multi-agent-start.md +104 -11
- package/content/pipeline/build/single-agent-resume.md +74 -8
- package/content/pipeline/build/single-agent-start.md +69 -12
- package/content/pipeline/finalization/materialize-plan-to-beads.md +473 -0
- package/content/pipeline/foundation/beads.md +6 -0
- package/content/pipeline/planning/implementation-plan-review.md +25 -0
- package/content/pipeline/planning/implementation-plan.md +75 -1
- package/content/pipeline/specification/mcp-tool-resource-contract.md +77 -0
- package/dist/cli/commands/adopt.d.ts.map +1 -1
- package/dist/cli/commands/adopt.js +33 -1
- package/dist/cli/commands/adopt.js.map +1 -1
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +46 -3
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/init-flag-families.d.ts +6 -1
- package/dist/cli/init-flag-families.d.ts.map +1 -1
- package/dist/cli/init-flag-families.js +59 -2
- package/dist/cli/init-flag-families.js.map +1 -1
- package/dist/cli/init-flag-families.test.js +86 -1
- package/dist/cli/init-flag-families.test.js.map +1 -1
- package/dist/config/schema.d.ts +2310 -126
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +26 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/config/schema.test.js +75 -2
- package/dist/config/schema.test.js.map +1 -1
- package/dist/config/validators/index.d.ts.map +1 -1
- package/dist/config/validators/index.js +2 -0
- package/dist/config/validators/index.js.map +1 -1
- package/dist/config/validators/mcp-server.d.ts +4 -0
- package/dist/config/validators/mcp-server.d.ts.map +1 -0
- package/dist/config/validators/mcp-server.js +37 -0
- package/dist/config/validators/mcp-server.js.map +1 -0
- package/dist/config/validators/mcp-server.test.d.ts +2 -0
- package/dist/config/validators/mcp-server.test.d.ts.map +1 -0
- package/dist/config/validators/mcp-server.test.js +47 -0
- package/dist/config/validators/mcp-server.test.js.map +1 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.d.ts +2 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.d.ts.map +1 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.js +75 -0
- package/dist/core/assembly/materialize-plan-to-beads-assembly.test.js.map +1 -0
- package/dist/e2e/project-type-overlays.test.js +83 -0
- package/dist/e2e/project-type-overlays.test.js.map +1 -1
- package/dist/project/adopt.d.ts.map +1 -1
- package/dist/project/adopt.js +3 -1
- package/dist/project/adopt.js.map +1 -1
- package/dist/project/detectors/coverage.test.js +1 -0
- package/dist/project/detectors/coverage.test.js.map +1 -1
- package/dist/project/detectors/disambiguate.d.ts.map +1 -1
- package/dist/project/detectors/disambiguate.js +6 -1
- package/dist/project/detectors/disambiguate.js.map +1 -1
- package/dist/project/detectors/disambiguate.test.js +18 -0
- package/dist/project/detectors/disambiguate.test.js.map +1 -1
- package/dist/project/detectors/index.d.ts.map +1 -1
- package/dist/project/detectors/index.js +2 -1
- package/dist/project/detectors/index.js.map +1 -1
- package/dist/project/detectors/mcp-server.d.ts +4 -0
- package/dist/project/detectors/mcp-server.d.ts.map +1 -0
- package/dist/project/detectors/mcp-server.js +91 -0
- package/dist/project/detectors/mcp-server.js.map +1 -0
- package/dist/project/detectors/mcp-server.test.d.ts +2 -0
- package/dist/project/detectors/mcp-server.test.d.ts.map +1 -0
- package/dist/project/detectors/mcp-server.test.js +115 -0
- package/dist/project/detectors/mcp-server.test.js.map +1 -0
- package/dist/project/detectors/types.d.ts +6 -2
- package/dist/project/detectors/types.d.ts.map +1 -1
- package/dist/project/detectors/types.js.map +1 -1
- package/dist/types/config.d.ts +8 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/wizard/copy/core.d.ts.map +1 -1
- package/dist/wizard/copy/core.js +4 -0
- package/dist/wizard/copy/core.js.map +1 -1
- package/dist/wizard/copy/index.d.ts.map +1 -1
- package/dist/wizard/copy/index.js +2 -0
- package/dist/wizard/copy/index.js.map +1 -1
- package/dist/wizard/copy/mcp-server.d.ts +3 -0
- package/dist/wizard/copy/mcp-server.d.ts.map +1 -0
- package/dist/wizard/copy/mcp-server.js +40 -0
- package/dist/wizard/copy/mcp-server.js.map +1 -0
- package/dist/wizard/copy/types.d.ts +5 -1
- package/dist/wizard/copy/types.d.ts.map +1 -1
- package/dist/wizard/flags.d.ts +9 -1
- package/dist/wizard/flags.d.ts.map +1 -1
- package/dist/wizard/questions.d.ts +4 -2
- package/dist/wizard/questions.d.ts.map +1 -1
- package/dist/wizard/questions.js +37 -0
- package/dist/wizard/questions.js.map +1 -1
- package/dist/wizard/questions.test.js +107 -0
- package/dist/wizard/questions.test.js.map +1 -1
- package/dist/wizard/wizard.d.ts +3 -2
- package/dist/wizard/wizard.d.ts.map +1 -1
- package/dist/wizard/wizard.js +3 -1
- package/dist/wizard/wizard.js.map +1 -1
- 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:
|
|
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:
|
|
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:
|
|
4
|
-
|
|
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:
|
|
7
|
-
version-pin:
|
|
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).
|